summaryrefslogtreecommitdiff
path: root/www/external
diff options
context:
space:
mode:
Diffstat (limited to 'www/external')
-rw-r--r--www/external/GCMIntentService.java543
-rw-r--r--www/external/NeuQuant.min.js55
-rw-r--r--www/external/angular-carousel.min.js124
-rw-r--r--www/external/angular-circular-navigation.min.js5
-rw-r--r--www/external/canvas-toBlob.min.js17
-rw-r--r--www/external/draggabilly.pkgd.min.js96
-rw-r--r--www/external/gifshot.min.js8
-rw-r--r--www/external/gifwriter.min.js64
-rw-r--r--www/external/imagesloaded.pkgd.min.js42
-rw-r--r--www/external/ion-pullup.min.js10
-rw-r--r--www/external/ionRadio.min.js12
-rw-r--r--www/external/ionic.content.banner.min.js12
-rw-r--r--www/external/ionic.scroll.sista.min.js28
-rw-r--r--www/external/ng-websocket.min.js31
-rw-r--r--www/external/origjs/NeuQuant.js389
-rw-r--r--www/external/origjs/README.TXT3
-rw-r--r--www/external/origjs/angular-carousel.js (renamed from www/external/angular-carousel.js)26
-rw-r--r--www/external/origjs/angular-circular-navigation.js (renamed from www/external/angular-circular-navigation.js)0
-rw-r--r--www/external/origjs/angular-ios9-uiwebview.patch.js73
-rw-r--r--www/external/origjs/canvas-toBlob.js (renamed from www/external/canvas-toBlob.js)0
-rw-r--r--www/external/origjs/draggabilly.pkgd.js (renamed from www/external/draggabilly.pkgd.js)0
-rw-r--r--www/external/origjs/gifwriter.js406
-rw-r--r--www/external/origjs/imagesloaded.pkgd.js (renamed from www/external/imagesloaded.pkgd.js)0
-rwxr-xr-xwww/external/origjs/ion-pullup.js (renamed from www/external/ion-pullup.js)0
-rw-r--r--www/external/origjs/ionRadio.js (renamed from www/external/ionRadio.js)0
-rw-r--r--www/external/origjs/ionic.content.banner.js (renamed from www/external/ionic.content.banner.js)0
-rw-r--r--www/external/origjs/ionic.scroll.sista.js (renamed from www/external/ionic.scroll.sista.js)0
-rw-r--r--www/external/origjs/ng-websocket.js (renamed from www/external/ng-websocket.js)0
-rw-r--r--www/external/origjs/packery.pkgd.js (renamed from www/external/packery.pkgd.js)0
-rw-r--r--www/external/packery.pkgd.min.js270
-rw-r--r--www/external/polyfill.min.js4
-rw-r--r--www/external/screwdriver.js151
32 files changed, 1804 insertions, 565 deletions
diff --git a/www/external/GCMIntentService.java b/www/external/GCMIntentService.java
deleted file mode 100644
index 9ffe5836..00000000
--- a/www/external/GCMIntentService.java
+++ /dev/null
@@ -1,543 +0,0 @@
-package com.adobe.phonegap.push;
-
-import android.annotation.SuppressLint;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v4.app.NotificationCompat;
-import android.text.Html;
-import android.util.Log;
-
-import com.google.android.gcm.GCMBaseIntentService;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Random;
-
-@SuppressLint("NewApi")
-public class GCMIntentService extends GCMBaseIntentService implements PushConstants {
-
- private static final String LOG_TAG = "PushPlugin_GCMIntentService";
- private static HashMap<Integer, ArrayList<String>> messageMap = new HashMap<Integer, ArrayList<String>>();
-
- public void setNotification(int notId, String message){
- ArrayList<String> messageList = messageMap.get(notId);
- if(messageList == null) {
- messageList = new ArrayList<String>();
- messageMap.put(notId, messageList);
- }
-
- if(message.isEmpty()){
- messageList.clear();
- }else{
- messageList.add(message);
- }
- }
-
- public GCMIntentService() {
- super("GCMIntentService");
- }
-
- @Override
- public void onRegistered(Context context, String regId) {
-
- Log.v(LOG_TAG, "onRegistered: " + regId);
-
- try {
- JSONObject json = new JSONObject().put(REGISTRATION_ID, regId);
-
- Log.v(LOG_TAG, "onRegistered: " + json.toString());
-
- PushPlugin.sendEvent( json );
- }
- catch(JSONException e) {
- // No message to the user is sent, JSON failed
- Log.e(LOG_TAG, "onRegistered: JSON exception");
- }
- }
-
- @Override
- public void onUnregistered(Context context, String regId) {
- Log.d(LOG_TAG, "onUnregistered - regId: " + regId);
- }
-
- @Override
- protected void onMessage(Context context, Intent intent) {
- Log.d(LOG_TAG, "onMessage - context: " + context);
-
- // Extract the payload from the message
- Bundle extras = intent.getExtras();
- if (extras != null) {
- // if we are in the foreground, just surface the payload, else post it to the statusbar
- if (PushPlugin.isInForeground()) {
- extras.putBoolean(FOREGROUND, true);
- PushPlugin.sendExtras(extras);
- }
- else {
- extras.putBoolean(FOREGROUND, false);
-
- // Send a notification if there is a message
- String message = this.getMessageText(extras);
- String title = getString(extras, TITLE, "");
- if ((message != null && message.length() != 0) ||
- (title != null && title.length() != 0)) {
- createNotification(context, extras);
- }
- }
- }
- }
-
- public void createNotification(Context context, Bundle extras) {
- NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- String appName = getAppName(this);
- String packageName = context.getPackageName();
- Resources resources = context.getResources();
-
- int notId = parseInt(NOT_ID, extras);
- Intent notificationIntent = new Intent(this, PushHandlerActivity.class);
- notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- notificationIntent.putExtra(PUSH_BUNDLE, extras);
- notificationIntent.putExtra(NOT_ID, notId);
-
- int requestCode = new Random().nextInt();
- PendingIntent contentIntent = PendingIntent.getActivity(this, requestCode, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- NotificationCompat.Builder mBuilder =
- new NotificationCompat.Builder(context)
- .setWhen(System.currentTimeMillis())
- .setContentTitle(getString(extras, TITLE))
- .setTicker(getString(extras, TITLE))
- .setContentIntent(contentIntent)
- .setAutoCancel(true);
-
- SharedPreferences prefs = context.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE);
- String localIcon = prefs.getString(ICON, null);
- String localIconColor = prefs.getString(ICON_COLOR, null);
- boolean soundOption = prefs.getBoolean(SOUND, true);
- //PP - make vibrate false
- //boolean vibrateOption = prefs.getBoolean(VIBRATE, true);
- boolean vibrateOption = false;
- Log.d(LOG_TAG, "stored icon=" + localIcon);
- Log.d(LOG_TAG, "stored iconColor=" + localIconColor);
- Log.d(LOG_TAG, "stored sound=" + soundOption);
- Log.d(LOG_TAG, "stored vibrate=" + vibrateOption);
-
- /*
- * Notification Vibration
- */
-
- setNotificationVibration(extras, vibrateOption, mBuilder);
-
- /*
- * Notification Icon Color
- *
- * Sets the small-icon background color of the notification.
- * To use, add the `iconColor` key to plugin android options
- *
- */
- setNotificationIconColor(getString(extras,"color"), mBuilder, localIconColor);
-
- /*
- * Notification Icon
- *
- * Sets the small-icon of the notification.
- *
- * - checks the plugin options for `icon` key
- * - if none, uses the application icon
- *
- * The icon value must be a string that maps to a drawable resource.
- * If no resource is found, falls
- *
- */
- setNotificationSmallIcon(context, extras, packageName, resources, mBuilder, localIcon);
-
- /*
- * Notification Large-Icon
- *
- * Sets the large-icon of the notification
- *
- * - checks the gcm data for the `image` key
- * - checks to see if remote image, loads it.
- * - checks to see if assets image, Loads It.
- * - checks to see if resource image, LOADS IT!
- * - if none, we don't set the large icon
- *
- */
- setNotificationLargeIcon(extras, packageName, resources, mBuilder);
-
- /*
- * Notification Sound
- */
- if (soundOption) {
- /* PP Enable Sound option */
- setNotificationSound(context, extras, mBuilder);
- }
-
- /*
- * LED Notification
- */
- setNotificationLedColor(extras, mBuilder);
-
- /*
- * Priority Notification
- */
- setNotificationPriority(extras, mBuilder);
-
- /*
- * Notification message
- */
- setNotificationMessage(notId, extras, mBuilder);
-
- /*
- * Notification count
- */
- setNotificationCount(extras, mBuilder);
-
- /*
- * Notication add actions
- */
- createActions(extras, mBuilder, resources, packageName);
-
- // PP add lights
- mBuilder.setLights(0xFFFF0000, 500, 500);
-
- //PP - http://stackoverflow.com/questions/29343974/custom-sound-in-android-push-notifications-gcm
- // mNotificationManager.notify(appName, notId, mBuilder.build());
- Notification notification = mBuilder.build();
- //notification.sound = Uri.parse("android.resource://" + context.getPackageName() + "/"+ R.raw.blop);
- //PP http://stackoverflow.com/questions/15449945/notification-sound-from-uri-parse-does-not-work
- //notification.sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getPackageName() + "/raw/blop");
- //notification.defaults |= Notification.DEFAULT_VIBRATE;
- mNotificationManager.notify((String) appName, notId, notification);
- }
-
- private void createActions(Bundle extras, NotificationCompat.Builder mBuilder, Resources resources, String packageName) {
- Log.d(LOG_TAG, "create actions");
- String actions = getString(extras, ACTIONS);
- if (actions != null) {
- try {
- JSONArray actionsArray = new JSONArray(actions);
- for (int i=0; i < actionsArray.length(); i++) {
- Log.d(LOG_TAG, "adding action");
- JSONObject action = actionsArray.getJSONObject(i);
- Log.d(LOG_TAG, "adding callback = " + action.getString(CALLBACK));
- Intent intent = new Intent(this, PushHandlerActivity.class);
- intent.putExtra(CALLBACK, action.getString(CALLBACK));
- intent.putExtra(PUSH_BUNDLE, extras);
- PendingIntent pIntent = PendingIntent.getActivity(this, i, intent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- mBuilder.addAction(resources.getIdentifier(action.getString(ICON), DRAWABLE, packageName),
- action.getString(TITLE), pIntent);
- }
- } catch(JSONException e) {
- // nope
- }
- }
- }
-
- private void setNotificationCount(Bundle extras, NotificationCompat.Builder mBuilder) {
- String msgcnt = getString(extras, MSGCNT);
- if (msgcnt == null) {
- msgcnt = getString(extras, BADGE);
- }
- if (msgcnt != null) {
- mBuilder.setNumber(Integer.parseInt(msgcnt));
- }
- }
-
- private void setNotificationVibration(Bundle extras, Boolean vibrateOption, NotificationCompat.Builder mBuilder) {
- String vibrationPattern = getString(extras, VIBRATION_PATTERN);
- if (vibrationPattern != null) {
- String[] items = vibrationPattern.replaceAll("\\[", "").replaceAll("\\]", "").split(",");
- long[] results = new long[items.length];
- for (int i = 0; i < items.length; i++) {
- try {
- results[i] = Long.parseLong(items[i]);
- } catch (NumberFormatException nfe) {}
- }
- mBuilder.setVibrate(results);
- } else {
- if (vibrateOption) {
- mBuilder.setDefaults(Notification.DEFAULT_VIBRATE);
- }
- }
- }
-
- private void setNotificationMessage(int notId, Bundle extras, NotificationCompat.Builder mBuilder) {
- String message = getMessageText(extras);
-
- String style = getString(extras, STYLE, STYLE_TEXT);
- if(STYLE_INBOX.equals(style)) {
- setNotification(notId, message);
-
- mBuilder.setContentText(message);
-
- ArrayList<String> messageList = messageMap.get(notId);
- Integer sizeList = messageList.size();
- if (sizeList > 1) {
- String sizeListMessage = sizeList.toString();
- String stacking = sizeList + " more";
- if (getString(extras, SUMMARY_TEXT) != null) {
- stacking = getString(extras, SUMMARY_TEXT);
- stacking = stacking.replace("%n%", sizeListMessage);
- }
- NotificationCompat.InboxStyle notificationInbox = new NotificationCompat.InboxStyle()
- .setBigContentTitle(getString(extras, TITLE))
- .setSummaryText(stacking);
-
- for (int i = messageList.size() - 1; i >= 0; i--) {
- notificationInbox.addLine(Html.fromHtml(messageList.get(i)));
- }
-
- mBuilder.setStyle(notificationInbox);
- } else {
- NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
- if (message != null) {
- bigText.bigText(message);
- bigText.setBigContentTitle(getString(extras, TITLE));
- mBuilder.setStyle(bigText);
- }
- }
- } else if (STYLE_PICTURE.equals(style)) {
- setNotification(notId, "");
-
- NotificationCompat.BigPictureStyle bigPicture = new NotificationCompat.BigPictureStyle();
- bigPicture.bigPicture(getBitmapFromURL(getString(extras, PICTURE)));
- bigPicture.setBigContentTitle(getString(extras, TITLE));
- bigPicture.setSummaryText(getString(extras, SUMMARY_TEXT));
-
- mBuilder.setContentTitle(getString(extras, TITLE));
- mBuilder.setContentText(message);
-
- mBuilder.setStyle(bigPicture);
- } else {
- setNotification(notId, "");
-
- NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
-
- if (message != null) {
- mBuilder.setContentText(Html.fromHtml(message));
-
- bigText.bigText(message);
- bigText.setBigContentTitle(getString(extras, TITLE));
-
- String summaryText = getString(extras, SUMMARY_TEXT);
- if (summaryText != null) {
- bigText.setSummaryText(summaryText);
- }
-
- mBuilder.setStyle(bigText);
- }
- /*
- else {
- mBuilder.setContentText("<missing message content>");
- }
- */
- }
- }
-
- private String getString(Bundle extras,String key) {
- String message = extras.getString(key);
- if (message == null) {
- message = extras.getString(GCM_NOTIFICATION+"."+key);
- }
- return message;
- }
-
- private String getString(Bundle extras,String key, String defaultString) {
- String message = extras.getString(key);
- if (message == null) {
- message = extras.getString(GCM_NOTIFICATION+"."+key, defaultString);
- }
- return message;
- }
-
- private String getMessageText(Bundle extras) {
- String message = getString(extras, MESSAGE);
- if (message == null) {
- message = getString(extras, BODY);
- }
- return message;
- }
-
- private void setNotificationSound(Context context, Bundle extras, NotificationCompat.Builder mBuilder) {
- String soundname = getString(extras, SOUNDNAME);
- if (soundname == null) {
- soundname = getString(extras, SOUND);
- }
- if (soundname != null) {
- Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
- + "://" + context.getPackageName() + "/raw/" + soundname);
- Log.d(LOG_TAG, sound.toString());
- mBuilder.setSound(sound);
- } else {
- mBuilder.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI);
- }
- }
-
- private void setNotificationLedColor(Bundle extras, NotificationCompat.Builder mBuilder) {
- String ledColor = getString(extras, LED_COLOR);
- if (ledColor != null) {
- // Converts parse Int Array from ledColor
- String[] items = ledColor.replaceAll("\\[", "").replaceAll("\\]", "").split(",");
- int[] results = new int[items.length];
- for (int i = 0; i < items.length; i++) {
- try {
- results[i] = Integer.parseInt(items[i]);
- } catch (NumberFormatException nfe) {}
- }
- if (results.length == 4) {
- mBuilder.setLights(Color.argb(results[0], results[1], results[2], results[3]), 500, 500);
- } else {
- Log.e(LOG_TAG, "ledColor parameter must be an array of length == 4 (ARGB)");
- }
- }
- }
-
- private void setNotificationPriority(Bundle extras, NotificationCompat.Builder mBuilder) {
- String priorityStr = getString(extras, PRIORITY);
- if (priorityStr != null) {
- try {
- Integer priority = Integer.parseInt(priorityStr);
- if (priority >= NotificationCompat.PRIORITY_MIN && priority <= NotificationCompat.PRIORITY_MAX) {
- mBuilder.setPriority(priority);
- } else {
- Log.e(LOG_TAG, "Priority parameter must be between -2 and 2");
- }
- } catch (NumberFormatException e) {
- e.printStackTrace();
- }
- }
- }
-
- private void setNotificationLargeIcon(Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder) {
- String gcmLargeIcon = getString(extras, IMAGE); // from gcm
- if (gcmLargeIcon != null) {
- if (gcmLargeIcon.startsWith("http://") || gcmLargeIcon.startsWith("https://")) {
- mBuilder.setLargeIcon(getBitmapFromURL(gcmLargeIcon));
- Log.d(LOG_TAG, "using remote large-icon from gcm");
- } else {
- AssetManager assetManager = getAssets();
- InputStream istr;
- try {
- istr = assetManager.open(gcmLargeIcon);
- Bitmap bitmap = BitmapFactory.decodeStream(istr);
- mBuilder.setLargeIcon(bitmap);
- Log.d(LOG_TAG, "using assets large-icon from gcm");
- } catch (IOException e) {
- int largeIconId = 0;
- largeIconId = resources.getIdentifier(gcmLargeIcon, DRAWABLE, packageName);
- if (largeIconId != 0) {
- Bitmap largeIconBitmap = BitmapFactory.decodeResource(resources, largeIconId);
- mBuilder.setLargeIcon(largeIconBitmap);
- Log.d(LOG_TAG, "using resources large-icon from gcm");
- } else {
- Log.d(LOG_TAG, "Not setting large icon");
- }
- }
- }
- }
- }
-
- private void setNotificationSmallIcon(Context context, Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder, String localIcon) {
- int iconId = 0;
- String icon = getString(extras, ICON);
- if (icon != null) {
- iconId = resources.getIdentifier(icon, DRAWABLE, packageName);
- Log.d(LOG_TAG, "using icon from plugin options");
- }
- else if (localIcon != null) {
- iconId = resources.getIdentifier(localIcon, DRAWABLE, packageName);
- Log.d(LOG_TAG, "using icon from plugin options");
- }
- if (iconId == 0) {
- Log.d(LOG_TAG, "no icon resource found - using application icon");
- iconId = context.getApplicationInfo().icon;
- }
- mBuilder.setSmallIcon(iconId);
- }
-
- private void setNotificationIconColor(String color, NotificationCompat.Builder mBuilder, String localIconColor) {
- int iconColor = 0;
- if (color != null) {
- try {
- iconColor = Color.parseColor(color);
- } catch (IllegalArgumentException e) {
- Log.e(LOG_TAG, "couldn't parse color from android options");
- }
- }
- else if (localIconColor != null) {
- try {
- iconColor = Color.parseColor(localIconColor);
- } catch (IllegalArgumentException e) {
- Log.e(LOG_TAG, "couldn't parse color from android options");
- }
- }
- if (iconColor != 0) {
- mBuilder.setColor(iconColor);
- }
- }
-
- public Bitmap getBitmapFromURL(String strURL) {
- try {
- URL url = new URL(strURL);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.setDoInput(true);
- connection.connect();
- InputStream input = connection.getInputStream();
- return BitmapFactory.decodeStream(input);
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- private static String getAppName(Context context) {
- CharSequence appName = context.getPackageManager().getApplicationLabel(context.getApplicationInfo());
- return (String)appName;
- }
-
- @Override
- public void onError(Context context, String errorId) {
- Log.e(LOG_TAG, "onError - errorId: " + errorId);
- // if we are in the foreground, just send the error
- if (PushPlugin.isInForeground()) {
- PushPlugin.sendError(errorId);
- }
- }
-
- private int parseInt(String value, Bundle extras) {
- int retval = 0;
-
- try {
- retval = Integer.parseInt(getString(extras, value));
- }
- catch(NumberFormatException e) {
- Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage());
- }
- catch(Exception e) {
- Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage());
- }
-
- return retval;
- }
-}
diff --git a/www/external/NeuQuant.min.js b/www/external/NeuQuant.min.js
new file mode 100644
index 00000000..12d6bb8d
--- /dev/null
+++ b/www/external/NeuQuant.min.js
@@ -0,0 +1,55 @@
+// NeuQuant.js
+// ===========
+
+/*
+ * NeuQuant Neural-Net Quantization Algorithm
+ * ------------------------------------------
+ *
+ * Copyright (c) 1994 Anthony Dekker
+ *
+ * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See
+ * "Kohonen neural networks for optimal colour quantization" in "Network:
+ * Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of
+ * the algorithm.
+ *
+ * Any party obtaining a copy of these files from the author, directly or
+ * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
+ * world-wide, paid up, royalty-free, nonexclusive right and license to deal in
+ * this software and documentation files (the "Software"), including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons who
+ * receive copies from any such party to do so, with the only requirement being
+ * that this copyright notice remain intact.
+ */
+
+/*
+ * This class handles Neural-Net quantization algorithm
+ * @author Kevin Weiner (original Java version - kweiner@fmsware.com)
+ * @author Thibault Imbert (AS3 version - bytearray.org)
+ * @version 0.1 AS3 implementation
+ * @version 0.2 JS->AS3 "translation" by antimatter15
+ * @version 0.3 JS clean up + using modern JS idioms by sole - http://soledadpenades.com
+ * Also implement fix in color conversion described at http://stackoverflow.com/questions/16371712/neuquant-js-javascript-color-quantization-hidden-bug-in-js-conversion
+ */
+
+NeuQuant=function(){function r(){function r(r,n,f){var o,t
+for(y=r,p=n,h=f,s=new Array(w),o=0;o<w;o++)s[o]=new Array(4),t=s[o],t[0]=t[1]=t[2]=(o<<d+8)/w|0,R[o]=k/w|0,P[o]=0}function n(){for(var r=[],n=new Array(w),f=0;f<w;f++)n[s[f][3]]=f
+for(var o=0,t=0;t<w;t++){var a=n[t]
+r[o++]=s[a][0],r[o++]=s[a][1],r[o++]=s[a][2]}return r}function f(){var r,n,f,o,t,a,u,c
+for(u=0,c=0,r=0;r<w;r++){for(t=s[r],f=r,o=t[1],n=r+1;n<w;n++)a=s[n],a[1]<o&&(f=n,o=a[1])
+if(a=s[f],r!=f&&(n=a[0],a[0]=t[0],t[0]=n,n=a[1],a[1]=t[1],t[1]=n,n=a[2],a[2]=t[2],t[2]=n,n=a[3],a[3]=t[3],t[3]=n),o!=u){for(O[u]=c+r>>1,n=u+1;n<o;n++)O[n]=r
+u=o,c=r}}for(O[u]=c+b>>1,n=u+1;n<256;n++)O[n]=b}function o(){var r,n,f,o,t,a,u,s,w,b,j,k,q,x
+for(p<Q&&(h=1),e=30+(h-1)/3,k=y,q=0,x=p,j=p/(3*h),b=j/g|0,s=I,a=F,u=a>>D,u<=1&&(u=0),r=0;r<u;r++)S[r]=s*((u*u-r*r)*K/(u*u))
+for(w=p<Q?3:p%A!==0?3*A:p%l!==0?3*l:p%m!==0?3*m:3*N,r=0;r<j;)if(f=(255&k[q+0])<<d,o=(255&k[q+1])<<d,t=(255&k[q+2])<<d,n=v(f,o,t),i(s,n,f,o,t),0!==u&&c(u,n,f,o,t),q+=w,q>=x&&(q-=p),r++,0===b&&(b=1),r%b===0)for(s-=s/e,a-=a/G,u=a>>D,u<=1&&(u=0),n=0;n<u;n++)S[n]=s*((u*u-n*n)*K/(u*u))}function t(r,n,f){var o,t,a,u,c,i,v
+for(c=1e3,v=-1,o=O[n],t=o-1;o<w||t>=0;)o<w&&(i=s[o],a=i[1]-n,a>=c?o=w:(o++,a<0&&(a=-a),u=i[0]-r,u<0&&(u=-u),a+=u,a<c&&(u=i[2]-f,u<0&&(u=-u),a+=u,a<c&&(c=a,v=i[3])))),t>=0&&(i=s[t],a=n-i[1],a>=c?t=-1:(t--,a<0&&(a=-a),u=i[0]-r,u<0&&(u=-u),a+=u,a<c&&(u=i[2]-f,u<0&&(u=-u),a+=u,a<c&&(c=a,v=i[3]))))
+return v}function a(){return o(),u(),f(),n()}function u(){var r
+for(r=0;r<w;r++)s[r][0]>>=d,s[r][1]>>=d,s[r][2]>>=d,s[r][3]=r}function c(r,n,f,o,t){var a,u,c,i,v,e,y
+for(c=n-r,c<-1&&(c=-1),i=n+r,i>w&&(i=w),a=n+1,u=n-1,e=1;a<i||u>c;){if(v=S[e++],a<i){y=s[a++]
+try{y[0]-=v*(y[0]-f)/M|0,y[1]-=v*(y[1]-o)/M|0,y[2]-=v*(y[2]-t)/M|0}catch(r){}}if(u>c){y=s[u--]
+try{y[0]-=v*(y[0]-f)/M|0,y[1]-=v*(y[1]-o)/M|0,y[2]-=v*(y[2]-t)/M|0}catch(r){}}}}function i(r,n,f,o,t){var a=s[n],u=r/I
+a[0]-=u*(a[0]-f)|0,a[1]-=u*(a[1]-o)|0,a[2]-=u*(a[2]-t)|0}function v(r,n,f){var o,t,a,u,c,i,v,e,y,p
+for(e=~(1<<31),y=e,i=-1,v=i,o=0;o<w;o++)p=s[o],t=p[0]-r,t<0&&(t=-t),a=p[1]-n,a<0&&(a=-a),t+=a,a=p[2]-f,a<0&&(a=-a),t+=a,t<e&&(e=t,i=o),u=t-(P[o]>>j-d),u<y&&(y=u,v=o),c=R[o]>>x,R[o]-=c,P[o]+=c<<q
+return R[i]+=z,P[i]-=B,v}var e,y,p,h,s,w=256,A=499,l=491,m=487,N=503,Q=3*N,b=w-1,d=4,g=100,j=16,k=1<<j,q=10,x=10,z=k>>x,B=k<<q-x,C=w>>3,D=6,E=1<<D,F=C*E,G=30,H=10,I=1<<H,J=8,K=1<<J,L=H+J,M=1<<L,O=[],P=[],R=[],S=[]
+r.apply(this,arguments)
+var T={}
+return T.map=t,T.process=a,T}return r}()
diff --git a/www/external/angular-carousel.min.js b/www/external/angular-carousel.min.js
new file mode 100644
index 00000000..34327d30
--- /dev/null
+++ b/www/external/angular-carousel.min.js
@@ -0,0 +1,124 @@
+//Angular Carousel - Mobile friendly touch carousel for AngularJS
+//@version v0.3.12 - 2015-06-11
+//@link http://revolunet.github.com/angular-carousel
+//@author Julien Bouquillon <julien@revolunet.com>
+//@license MIT License, http://www.opensource.org/licenses/MIT
+//Angular touch carousel with CSS GPU accel and slide buffering
+//http://github.com/revolunet/angular-carousel
+
+// Modified by PP for mobile friendly touch, start without auto slide but enabled it if tapped
+// and logic to wait for an image to load before it slides to the next one
+//
+/* jshint ignore:start */
+/*global angular */
+
+angular.module("angular-carousel",["ngTouch","angular-carousel.shifty"]),angular.module("angular-carousel").directive("rnCarouselAutoSlide",["$interval","$timeout","imageLoadingDataShare","carouselUtils",function(t,e,n,r){return{restrict:"A",link:function(t,e,n){var i=function(){t.autoSlider&&(t.autoSlider=null)},o=function(){0==r.isStopped()&&t.autoSlide()},a=function(){r.setStop(!r.getStop()),r.isStopped()&&r.setIndex(t.carouselIndex),t.autoSlider?(r.setStop(!0),r.setIndex(t.carouselIndex),i()):(r.setStop(!1),o())}
+r.setStop(!1),t.$watch("carouselIndex",o),n.hasOwnProperty("rnCarouselPauseOnHover")&&"false"!==n.rnCarouselPauseOnHover&&(n.hasOwnProperty("rnPlatform")&&"desktop"==n.rnPlatform?(e.off("click",a),e.on("click",a)):(e.off("touchend",a),e.on("touchend",a))),t.$on("$destroy",function(){i(),e.off("touchend",a),e.off("click",a)})}}}]),angular.module("angular-carousel").directive("rnCarouselIndicators",["$parse",function(t){return{restrict:"A",scope:{slides:"=",index:"=rnCarouselIndex"},templateUrl:"carousel-indicators.html",link:function(e,n,r){var i=t(r.rnCarouselIndex)
+e.goToSlide=function(t){i.assign(e.$parent.$parent,t)}}}}]),angular.module("angular-carousel").run(["$templateCache",function(t){t.put("carousel-indicators.html",'<div class="rn-carousel-indicator">\n<span ng-repeat="slide in slides" ng-class="{active: $index==index}" ng-click="goToSlide($index)">●</span></div>')}]),function(){"use strict"
+angular.module("angular-carousel").service("DeviceCapabilities",function(){function t(){var t="transform",e="webkitTransform"
+return"undefined"!=typeof document.body.style[t]?["webkit","moz","o","ms"].every(function(e){var n="-"+e+"-transform"
+return"undefined"==typeof document.body.style[n]||(t=n,!1)}):t="undefined"!=typeof document.body.style[e]?"-webkit-transform":void 0,t}function e(){var t,e=document.createElement("p"),n={webkitTransform:"-webkit-transform",msTransform:"-ms-transform",transform:"transform"}
+document.body.insertBefore(e,null)
+for(var r in n)void 0!==e.style[r]&&(e.style[r]="translate3d(1px,1px,1px)",t=window.getComputedStyle(e).getPropertyValue(n[r]))
+return document.body.removeChild(e),void 0!==t&&t.length>0&&"none"!==t}return{has3d:e(),transformProperty:t()}}).service("computeCarouselSlideStyle",["DeviceCapabilities",function(t){return function(e,n,r){var i,o={display:"inline-block"},a=100*e+n,u=t.has3d?"translate3d("+a+"%, 0, 0)":"translate3d("+a+"%, 0)",s=(100-Math.abs(a))/100
+if(t.transformProperty)if("fadeAndSlide"==r)o[t.transformProperty]=u,i=0,Math.abs(a)<100&&(i=.3+.7*s),o.opacity=i
+else if("hexagon"==r){var c=100,l=0,f=60*(s-1)
+c=n<e*-100?100:0,l=n<e*-100?f:-f,o[t.transformProperty]=u+" rotateY("+l+"deg)",o[t.transformProperty+"-origin"]=c+"% 50%"}else if("zoom"==r){o[t.transformProperty]=u
+var d=1
+Math.abs(a)<100&&(d=1+2*(1-s)),o[t.transformProperty]+=" scale("+d+")",o[t.transformProperty+"-origin"]="50% 50%",i=0,Math.abs(a)<100&&(i=.3+.7*s),o.opacity=i}else o[t.transformProperty]=u
+else o["margin-left"]=a+"%"
+return o}}]).factory("carouselUtils",function(){var t=!1,e=0,n=0
+return{setDuration:function(t){e=t},getDuration:function(){return e},setStop:function(e){t=e,t&&console.log("Paused at "+n)},setIndex:function(t){n=t},getIndex:function(){return n},getStop:function(){return t},isStopped:function(){return t},hello:function(){}}}).service("createStyleString",function(){return function(t){var e=[]
+return angular.forEach(t,function(t,n){e.push(n+":"+t)}),e.join(";")}}).directive("rnCarousel",["$swipe","$window","$document","$parse","$compile","$timeout","$interval","computeCarouselSlideStyle","createStyleString","Tweenable","imageLoadingDataShare","carouselUtils",function(t,e,n,r,i,o,a,u,s,c,l,f){function d(t,e,n){var r=n
+return t.every(function(t,n){return!angular.equals(t,e)||(r=n,!1)}),r}var h=0
+e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame
+return{restrict:"A",scope:!0,compile:function(a,p){var g,m,v=a[0].querySelector("li"),w=v?v.attributes:[],y=!1,S=!1
+return["ng-repeat","data-ng-repeat","ng:repeat","x-ng-repeat"].every(function(t){var e=w[t]
+if(angular.isDefined(e)){var n=e.value.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),r=n[3]
+if(g=n[1],m=n[2],g)return angular.isDefined(p.rnCarouselBuffered)&&(S=!0,e.value=g+" in "+m+"|carouselSlice:carouselBufferIndex:carouselBufferSize",r&&(e.value+=" track by "+r)),y=!0,!1}return!0}),function(a,p,g,v){function w(){return p[0].querySelectorAll("ul[rn-carousel] > li")}function _(t){N=!0,F({x:t.clientX,y:t.clientY},t)}function I(t){var e=100*a.carouselBufferIndex+t
+angular.forEach(w(),function(t,n){t.style.cssText=s(u(n,e,z.transitionType))})}function x(t,e){if(void 0===t&&(t=a.carouselIndex),e=e||{},e.animate===!1||"none"===z.transitionType)return U=!1,R=t*-100,a.carouselIndex=t,void O()
+U=!0
+var n=new c
+n.tween({from:{x:R},to:{x:t*-100},duration:z.transitionDuration,easing:z.transitionEasing,step:function(t){I(t.x)},finish:function(){a.$apply(function(){a.carouselIndex=t,R=t*-100,O(),o(function(){U=!1},0,!1)})}})}function C(){var t=p[0].getBoundingClientRect()
+return t.width?t.width:t.right-t.left}function b(){Q=C()}function k(){j||(j=!0,n.bind("mouseup",_))}function M(){j&&(j=!1,n.unbind("mouseup",_))}function T(t,e){if(!(U||H.length<=1))return b(),L=p[0].querySelector("li").getBoundingClientRect().left,D=!0,A=t.x,!1}function P(t,e){var n,r
+if(k(),D&&(n=t.x,r=A-n,r>2||r<-2)){N=!0
+var i=R+100*-r/Q
+I(i)}return!1}function F(t,e,n){if((!e||N)&&(M(),D=!1,N=!1,B=A-t.x,0!==B&&!U))if(R+=100*-B/Q,z.isSequential){var i=z.moveTreshold*Q,o=-B,u=-Math[o>=0?"ceil":"floor"](o/Q),s=Math.abs(o)>i
+H&&u+a.carouselIndex>=H.length&&(u=H.length-1-a.carouselIndex),u+a.carouselIndex<0&&(u=-a.carouselIndex)
+var c=s?u:0
+B=a.carouselIndex+c,x(B),void 0!==g.rnCarouselOnInfiniteScrollRight&&0===u&&0!==a.carouselIndex&&(r(g.rnCarouselOnInfiniteScrollRight)(a),x(0)),void 0!==g.rnCarouselOnInfiniteScrollLeft&&0===u&&0===a.carouselIndex&&0===c&&(r(g.rnCarouselOnInfiniteScrollLeft)(a),x(H.length))}else a.$apply(function(){a.carouselIndex=parseInt(-R/100,10),O()})}function O(){var t=0,e=(a.carouselBufferSize-1)/2
+S?(t=a.carouselIndex<=e?0:H&&H.length<a.carouselBufferSize?0:H&&a.carouselIndex>H.length-a.carouselBufferSize?H.length-a.carouselBufferSize:a.carouselIndex-e,a.carouselBufferIndex=t,o(function(){I(R)},0,!1)):o(function(){I(R)},0,!1)}function $(){b(),x()}h++
+var D,A,B,q={transitionType:g.rnCarouselTransition||"slide",transitionEasing:g.rnCarouselEasing||"easeTo",transitionDuration:parseFloat(g.rnCarouselDuration,10)||300,isSequential:!0,autoSlideDuration:3,bufferSize:9,moveTreshold:.1,defaultIndex:0},z=angular.extend({},q),E=!1,R=0,N=!1,H=[],Q=null,L=null,j=!1,U=!1
+"true"!==g.rnSwipeDisabled&&t.bind(p,{start:T,move:P,end:F,cancel:function(t){F({},t)}}),a.nextSlide=function(t){if(1!=f.isStopped()){var e=a.carouselIndex+1
+e>H.length-1&&e--,1!=l.get()?x(e,t):a.autoSlide()}},a.prevSlide=function(t){var e=a.carouselIndex-1
+e<0&&(e=H.length-1),x(e,t)}
+var W=!0
+if(a.carouselIndex=0,y||(H=[],angular.forEach(w(),function(t,e){H.push({id:e})})),void 0!==g.rnCarouselControls){var Y=y?m.replace("::","")+".length - 1":H.length-1,G='<div class="rn-carousel-controls">\n <span class="rn-carousel-control rn-carousel-control-prev" ng-click="prevSlide()" ng-if="carouselIndex > 0"></span>\n <span class="rn-carousel-control rn-carousel-control-next" ng-click="nextSlide()" ng-if="carouselIndex < '+Y+'"></span>\n</div>'
+p.parent().append(i(angular.element(G))(a))}if(void 0!==g.rnCarouselAutoSlide){var V=parseFloat(g.rnCarouselAutoSlide,10)||z.autoSlideDuration
+f.setDuration(V),console.log("Setting duration - should only happen once"),a.autoSlide=function(){if(a.autoSlider&&(a.autoSlider=null),0==f.isStopped()){var t=f.getDuration(),e=1e3*t
+e<5&&(console.log("duration is too small at "+e+" making it to 5"),e=5),a.autoSlider=o(function(){a.nextSlide()},e)}else console.log("We are stopped, doing nothing")}}if(g.rnCarouselDefaultIndex){var X=r(g.rnCarouselDefaultIndex)
+z.defaultIndex=X(a.$parent)||0}var J=null
+if(g.rnCarouselIndex){var K=function(t){t<0||Z.assign(a.$parent,t)},Z=r(g.rnCarouselIndex)
+angular.isFunction(Z.assign)?(a.$watch("carouselIndex",function(t){K(t)}),a.$parent.$watch(function(){return Z(a.$parent)},function(t,e){J=t,void 0!==t&&null!==t&&(H&&H.length>0&&t>=H.length?(t=H.length-1,K(t)):H&&t<0&&(t=0,K(t)),U||x(t,{animate:!W}),W=!1)}),E=!0,z.defaultIndex&&x(z.defaultIndex,{animate:!W})):isNaN(g.rnCarouselIndex)||x(parseInt(g.rnCarouselIndex,10),{animate:!1})}else x(z.defaultIndex,{animate:!W}),W=!1
+if(g.rnCarouselLocked&&a.$watch(g.rnCarouselLocked,function(t,e){U=t===!0}),y){var tt=void 0!==g.rnCarouselDeepWatch
+a[tt?"$watch":"$watchCollection"](m,function(t,e){if(H=t,J&&(a.carouselIndex=J,J=null),tt&&angular.isArray(t)){var n=e[a.carouselIndex],r=d(t,n,a.carouselIndex)
+x(r,{animate:!1})}else x(a.carouselIndex,{animate:!1})},!0)}a.$on("$destroy",function(){M()}),a.carouselBufferIndex=0,a.carouselBufferSize=z.bufferSize
+var et=angular.element(e)
+et.bind("orientationchange",$),et.bind("resize",$),a.$on("$destroy",function(){M(),et.unbind("orientationchange",$),et.unbind("resize",$)})}}}}])}(),angular.module("angular-carousel.shifty",[]).factory("Tweenable",function(){return function(t){var e=function(){"use strict"
+function e(){}function n(t,e){var n
+for(n in t)Object.hasOwnProperty.call(t,n)&&e(n)}function r(t,e){return n(e,function(n){t[n]=e[n]}),t}function i(t,e){n(e,function(n){"undefined"==typeof t[n]&&(t[n]=e[n])})}function o(t,e,n,r,i,o,u){var s,c=(t-o)/i
+for(s in e)e.hasOwnProperty(s)&&(e[s]=a(n[s],r[s],f[u[s]],c))
+return e}function a(t,e,n,r){return t+(e-t)*n(r)}function u(t,e){var r=l.prototype.filter,i=t._filterArgs
+n(r,function(n){"undefined"!=typeof r[n][e]&&r[n][e].apply(t,i)})}function s(t,e,n,r,i,a,s,c,l){w=e+n,y=Math.min(v(),w),S=y>=w,_=n-(w-y),t.isPlaying()&&!S?(t._scheduleId=l(t._timeoutHandler,g),u(t,"beforeTween"),o(y,r,i,a,n,e,s),u(t,"afterTween"),c(r,t._attachment,_)):S&&(c(a,t._attachment,_),t.stop(!0))}function c(t,e){var r={}
+return"string"==typeof e?n(t,function(t){r[t]=e}):n(t,function(t){r[t]||(r[t]=e[t]||h)}),r}function l(t,e){this._currentState=t||{},this._configured=!1,this._scheduleFunction=d,"undefined"!=typeof e&&this.setConfig(e)}var f,d,h="linear",p=500,g=1e3/60,m=Date.now?Date.now:function(){return+new Date},v="undefined"!=typeof SHIFTY_DEBUG_NOW?SHIFTY_DEBUG_NOW:m
+d="undefined"!=typeof window?window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozCancelRequestAnimationFrame&&window.mozRequestAnimationFrame||setTimeout:setTimeout
+var w,y,S,_
+return l.prototype.tween=function(t){return this._isTweening?this:(void 0===t&&this._configured||this.setConfig(t),this._timestamp=v(),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._start=t.start||e,this._step=t.step||e,this._finish=t.finish||e,this._duration=t.duration||p,this._currentState=t.from||this.get(),this._originalState=this.get(),this._targetState=t.to||this.get()
+var n=this._currentState,r=this._targetState
+return i(r,n),this._easing=c(n,t.easing||h),this._filterArgs=[n,this._originalState,r,this._easing],u(this,"tweenCreated"),this},l.prototype.get=function(){return r({},this._currentState)},l.prototype.set=function(t){this._currentState=t},l.prototype.pause=function(){return this._pausedAtTime=v(),this._isPaused=!0,this},l.prototype.resume=function(){this._isPaused&&(this._timestamp+=v()-this._pausedAtTime),this._isPaused=!1,this._isTweening=!0
+var t=this
+return this._timeoutHandler=function(){s(t,t._timestamp,t._duration,t._currentState,t._originalState,t._targetState,t._easing,t._step,t._scheduleFunction)},this._timeoutHandler(),this},l.prototype.seek=function(t){return this._timestamp=v()-t,this.isPlaying()||(this._isTweening=!0,this._isPaused=!1,s(this,this._timestamp,this._duration,this._currentState,this._originalState,this._targetState,this._easing,this._step,this._scheduleFunction),this._timeoutHandler(),this.pause()),this},l.prototype.stop=function(n){return this._isTweening=!1,this._isPaused=!1,this._timeoutHandler=e,(t.cancelAnimationFrame||t.webkitCancelAnimationFrame||t.oCancelAnimationFrame||t.msCancelAnimationFrame||t.mozCancelRequestAnimationFrame||t.clearTimeout)(this._scheduleId),n&&(r(this._currentState,this._targetState),u(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,r(l,{now:v,each:n,tweenProps:o,tweenProp:a,applyFilter:u,shallowCopy:r,defaults:i,composeEasingObject:c}),t.Tweenable=l,l}()
+!function(){e.shallowCopy(e.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-Math.cos(t*(Math.PI/2))+1},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:-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*(-Math.pow(2,-10*--t)+2)},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 t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?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?.5*(t*t*(((e*=1.525)+1)*t-e)):.5*((t-=2)*t*(((e*=1.525)+1)*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?.5*(t*t*(((e*=1.525)+1)*t-e)):.5*((t-=2)*t*(((e*=1.525)+1)*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 t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bouncePast:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?2-(7.5625*(t-=1.5/2.75)*t+.75):t<2.5/2.75?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,r,i,o){function a(t){return((h*t+p)*t+g)*t}function u(t){return((m*t+v)*t+w)*t}function s(t){return(3*h*t+2*p)*t+g}function c(t){return 1/(200*t)}function l(t,e){return u(d(t,e))}function f(t){return t>=0?t:0-t}function d(t,e){var n,r,i,o,u,c
+for(i=t,c=0;c<8;c++){if(o=a(i)-t,f(o)<e)return i
+if(u=s(i),f(u)<1e-6)break
+i-=o/u}if(n=0,r=1,i=t,i<n)return n
+if(i>r)return r
+for(;n<r;){if(o=a(i),f(o-t)<e)return i
+t>o?n=i:r=i,i=.5*(r-n)+n}return i}var h=0,p=0,g=0,m=0,v=0,w=0
+return g=3*e,p=3*(r-e)-g,h=1-g-p,w=3*n,v=3*(i-n)-w,m=1-w-v,l(t,c(o))}function n(e,n,r,i){return function(o){return t(o,e,n,r,i,1)}}e.setBezierFunction=function(t,r,i,o,a){var u=n(r,i,o,a)
+return u.x1=r,u.y1=i,u.x2=o,u.y2=a,e.prototype.formula[t]=u},e.unsetBezierFunction=function(t){delete e.prototype.formula[t]}}(),function(){function t(t,n,r,i,o){return e.tweenProps(i,n,t,r,1,0,o)}var n=new e
+n._filterArgs=[],e.interpolate=function(r,i,o,a){var u=e.shallowCopy({},r),s=e.composeEasingObject(r,a||"linear")
+n.set({})
+var c=n._filterArgs
+c.length=0,c[0]=u,c[1]=r,c[2]=i,c[3]=s,e.applyFilter(n,"tweenCreated"),e.applyFilter(n,"beforeTween")
+var l=t(r,u,i,o,s)
+return e.applyFilter(n,"afterTween"),l}}(),function(t){function e(t,e){M.length=0
+var n,r=t.length
+for(n=0;n<r;n++)M.push("_"+e+"_"+n)
+return M}function n(t){var e=t.match(_)
+return e?(1===e.length||t[0].match(S))&&e.unshift(""):e=["",""],e.join(k)}function r(e){t.each(e,function(t){var n=e[t]
+"string"==typeof n&&n.match(b)&&(e[t]=i(n))})}function i(t){return s(b,t,o)}function o(t){var e=a(t)
+return"rgb("+e[0]+","+e[1]+","+e[2]+")"}function a(t){return t=t.replace(/#/,""),3===t.length&&(t=t.split(""),t=t[0]+t[0]+t[1]+t[1]+t[2]+t[2]),T[0]=u(t.substr(0,2)),T[1]=u(t.substr(2,2)),T[2]=u(t.substr(4,2)),T}function u(t){return parseInt(t,16)}function s(t,e,n){var r=e.match(t),i=e.replace(t,k)
+if(r)for(var o,a=r.length,u=0;u<a;u++)o=r.shift(),i=i.replace(k,n(o))
+return i}function c(t){return s(x,t,l)}function l(t){for(var e=t.match(I),n=e.length,r=t.match(C)[0],i=0;i<n;i++)r+=parseInt(e[i],10)+","
+return r=r.slice(0,-1)+")"}function f(r){var i={}
+return t.each(r,function(t){var o=r[t]
+if("string"==typeof o){var a=v(o)
+i[t]={formatString:n(o),chunkNames:e(a,t)}}}),i}function d(e,n){t.each(n,function(t){for(var r=e[t],i=v(r),o=i.length,a=0;a<o;a++)e[n[t].chunkNames[a]]=+i[a]
+delete e[t]})}function h(e,n){t.each(n,function(t){var r=e[t],i=p(e,n[t].chunkNames),o=g(i,n[t].chunkNames)
+r=m(n[t].formatString,o),e[t]=c(r)})}function p(t,e){for(var n,r={},i=e.length,o=0;o<i;o++)n=e[o],r[n]=t[n],delete t[n]
+return r}function g(t,e){P.length=0
+for(var n=e.length,r=0;r<n;r++)P.push(t[e[r]])
+return P}function m(t,e){for(var n=t,r=e.length,i=0;i<r;i++)n=n.replace(k,+e[i].toFixed(4))
+return n}function v(t){return t.match(I)}function w(e,n){t.each(n,function(t){for(var r=n[t],i=r.chunkNames,o=i.length,a=e[t].split(" "),u=a[a.length-1],s=0;s<o;s++)e[i[s]]=a[s]||u
+delete e[t]})}function y(e,n){t.each(n,function(t){for(var r=n[t],i=r.chunkNames,o=i.length,a="",u=0;u<o;u++)a+=" "+e[i[u]],delete e[i[u]]
+e[t]=a.substr(1)})}var S=/(\d|\-|\.)/,_=/([^\-0-9\.]+)/g,I=/[0-9.\-]+/g,x=new RegExp("rgb\\("+I.source+/,\s*/.source+I.source+/,\s*/.source+I.source+"\\)","g"),C=/^.*\(/,b=/#([0-9]|[a-f]){3,6}/gi,k="VAL",M=[],T=[],P=[]
+t.prototype.filter.token={tweenCreated:function(t,e,n,i){r(t),r(e),r(n),this._tokenData=f(t)},beforeTween:function(t,e,n,r){w(r,this._tokenData),d(t,this._tokenData),d(e,this._tokenData),d(n,this._tokenData)},afterTween:function(t,e,n,r){h(t,this._tokenData),h(e,this._tokenData),h(n,this._tokenData),y(r,this._tokenData)}}}(e)}(window),window.Tweenable}),function(){"use strict"
+angular.module("angular-carousel").filter("carouselSlice",function(){return function(t,e,n){return angular.isArray(t)?t.slice(e,e+n):angular.isObject(t)?t:void 0}})}()
diff --git a/www/external/angular-circular-navigation.min.js b/www/external/angular-circular-navigation.min.js
new file mode 100644
index 00000000..3b466c2f
--- /dev/null
+++ b/www/external/angular-circular-navigation.min.js
@@ -0,0 +1,5 @@
+// https://github.com/maxklenk/angular-circular-navigation/blob/master/LICENSE
+// PP - Modified to show at right angles
+!function(){"use strict"
+var o=window.angular?window.angular:"undefined"!=typeof require?require("angular"):void 0,n=o.module("angularCircularNavigation",[]).directive("circular",["$compile",function(o){return{restrict:"EA",scope:{options:"="},template:'<button ng-click="toggleMenu()" class="cn-button {{options.button.size}}" ng-class="options.button.cssClass" style="background: {{options.button.background ? options.button.background : options.background}}; color: {{options.button.color ? options.button.color :options.color}};">{{options.content}}</button><div class="cn-wrapper {{options.size}} items-{{options.items.length}}" ng-class="{\'opened-nav\':options.isOpen}"><ul><li ng-repeat="item in options.items"><a ng-hide="item.empty" ng-click="perform(options, item)" ng-class="{\'is-active\': item.isActive}" class="{{item.cssClass}}" style="background: {{item.background ? item.background : options.background}}; color: {{item.color ? item.color : options.color}};"><span>{{item.content}}</span></a></li></ul></div>',controller:["$scope","$element","$attrs",function(o,n,t){o.toggleMenu=function(){"function"==typeof o.options.button.onclick?o.options.button.onclick():o.options.isOpen=!o.options.isOpen},o.perform=function(n,t){"function"==typeof t.onclick&&t.onclick(n,t),o.options.toggleOnClick&&o.toggleMenu()}}]}}])
+"function"==typeof define&&define.amd?define("circular",["angular"],n):"undefined"!=typeof exports&&"undefined"!=typeof module&&(module.exports=n)}()
diff --git a/www/external/canvas-toBlob.min.js b/www/external/canvas-toBlob.min.js
new file mode 100644
index 00000000..6651861b
--- /dev/null
+++ b/www/external/canvas-toBlob.min.js
@@ -0,0 +1,17 @@
+/* canvas-toBlob.js
+ * A canvas.toBlob() implementation.
+ * 2013-12-27
+ *
+ * By Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr
+ * License: MIT
+ * See https://github.com/eligrey/canvas-toBlob.js/blob/master/LICENSE.md
+ */
+!function(t){"use strict"
+var o,e=t.Uint8Array,n=t.HTMLCanvasElement,i=n&&n.prototype,s=/\s*;\s*base64\s*(?:;|$)/i,a="toDataURL",l=function(t){for(var n,i,s,a=t.length,l=new e(a/4*3|0),r=0,b=0,d=[0,0],f=0,c=0;a--;)i=t.charCodeAt(r++),n=o[i-43],255!==n&&n!==s&&(d[1]=d[0],d[0]=i,c=c<<6|n,f++,4===f&&(l[b++]=c>>>16,61!==d[1]&&(l[b++]=c>>>8),61!==d[0]&&(l[b++]=c),f=0))
+return l}
+e&&(o=new e([62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,0,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51])),n&&!i.toBlob&&(i.toBlob=function(t,o){if(o||(o="image/png"),this.mozGetAsFile)return void t(this.mozGetAsFile("canvas",o))
+if(this.msToBlob&&/^\s*image\/png\s*(?:$|;)/i.test(o))return void t(this.msToBlob())
+var n,i=Array.prototype.slice.call(arguments,1),r=this[a].apply(this,i),b=r.indexOf(","),d=r.substring(b+1),f=s.test(r.substring(0,b))
+Blob.fake?(n=new Blob,f?n.encoding="base64":n.encoding="URI",n.data=d,n.size=d.length):e&&(n=f?new Blob([l(d)],{type:o}):new Blob([decodeURIComponent(d)],{type:o})),t(n)},i.toDataURLHD?i.toBlobHD=function(){a="toDataURLHD"
+var t=this.toBlob()
+return a="toDataURL",t}:i.toBlobHD=i.toBlob)}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content||this)
diff --git a/www/external/draggabilly.pkgd.min.js b/www/external/draggabilly.pkgd.min.js
new file mode 100644
index 00000000..93e9bdcb
--- /dev/null
+++ b/www/external/draggabilly.pkgd.min.js
@@ -0,0 +1,96 @@
+/*!
+ * Draggabilly PACKAGED v2.1.0
+ * Make that shiz draggable
+ * http://draggabilly.desandro.com
+ * MIT license
+ */
+!function(t,i){"function"==typeof define&&define.amd?define("jquery-bridget/jquery-bridget",["jquery"],function(e){i(t,e)}):"object"==typeof module&&module.exports?module.exports=i(t,require("jquery")):t.jQueryBridget=i(t,t.jQuery)}(window,function(t,i){function e(e,r,a){function h(t,i,n){var o,r="$()."+e+'("'+i+'")'
+return t.each(function(t,h){var d=a.data(h,e)
+if(!d)return void s(e+" not initialized. Cannot call methods, i.e. "+r)
+var u=d[i]
+if(!u||"_"==i.charAt(0))return void s(r+" is not a valid method")
+var p=u.apply(d,n)
+o=void 0===o?p:o}),void 0!==o?o:t}function d(t,i){t.each(function(t,n){var o=a.data(n,e)
+o?(o.option(i),o._init()):(o=new r(n,i),a.data(n,e,o))})}a=a||i||t.jQuery,a&&(r.prototype.option||(r.prototype.option=function(t){a.isPlainObject(t)&&(this.options=a.extend(!0,this.options,t))}),a.fn[e]=function(t){if("string"==typeof t){var i=o.call(arguments,1)
+return h(this,t,i)}return d(this,t),this},n(a))}function n(t){!t||t&&t.bridget||(t.bridget=e)}var o=Array.prototype.slice,r=t.console,s="undefined"==typeof r?function(){}:function(t){r.error(t)}
+return n(i||t.jQuery),e}),function(t,i){"function"==typeof define&&define.amd?define("get-size/get-size",[],function(){return i()}):"object"==typeof module&&module.exports?module.exports=i():t.getSize=i()}(window,function(){function t(t){var i=parseFloat(t),e=t.indexOf("%")==-1&&!isNaN(i)
+return e&&i}function i(){}function e(){for(var t={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},i=0;i<d;i++){var e=h[i]
+t[e]=0}return t}function n(t){var i=getComputedStyle(t)
+return i||a("Style returned "+i+". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1"),i}function o(){if(!u){u=!0
+var i=document.createElement("div")
+i.style.width="200px",i.style.padding="1px 2px 3px 4px",i.style.borderStyle="solid",i.style.borderWidth="1px 2px 3px 4px",i.style.boxSizing="border-box"
+var e=document.body||document.documentElement
+e.appendChild(i)
+var o=n(i)
+r.isBoxSizeOuter=s=200==t(o.width),e.removeChild(i)}}function r(i){if(o(),"string"==typeof i&&(i=document.querySelector(i)),i&&"object"==typeof i&&i.nodeType){var r=n(i)
+if("none"==r.display)return e()
+var a={}
+a.width=i.offsetWidth,a.height=i.offsetHeight
+for(var u=a.isBorderBox="border-box"==r.boxSizing,p=0;p<d;p++){var c=h[p],f=r[c],g=parseFloat(f)
+a[c]=isNaN(g)?0:g}var l=a.paddingLeft+a.paddingRight,v=a.paddingTop+a.paddingBottom,m=a.marginLeft+a.marginRight,y=a.marginTop+a.marginBottom,b=a.borderLeftWidth+a.borderRightWidth,P=a.borderTopWidth+a.borderBottomWidth,E=u&&s,_=t(r.width)
+_!==!1&&(a.width=_+(E?0:l+b))
+var x=t(r.height)
+return x!==!1&&(a.height=x+(E?0:v+P)),a.innerWidth=a.width-(l+b),a.innerHeight=a.height-(v+P),a.outerWidth=a.width+m,a.outerHeight=a.height+y,a}}var s,a="undefined"==typeof console?i:function(t){console.error(t)},h=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"],d=h.length,u=!1
+return r}),function(t,i){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",i):"object"==typeof module&&module.exports?module.exports=i():t.EvEmitter=i()}(this,function(){function t(){}var i=t.prototype
+return i.on=function(t,i){if(t&&i){var e=this._events=this._events||{},n=e[t]=e[t]||[]
+return n.indexOf(i)==-1&&n.push(i),this}},i.once=function(t,i){if(t&&i){this.on(t,i)
+var e=this._onceEvents=this._onceEvents||{},n=e[t]=e[t]||[]
+return n[i]=!0,this}},i.off=function(t,i){var e=this._events&&this._events[t]
+if(e&&e.length){var n=e.indexOf(i)
+return n!=-1&&e.splice(n,1),this}},i.emitEvent=function(t,i){var e=this._events&&this._events[t]
+if(e&&e.length){var n=0,o=e[n]
+i=i||[]
+for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o]
+s&&(this.off(t,o),delete r[o]),o.apply(this,i),n+=s?0:1,o=e[n]}return this}},t}),function(t,i){"function"==typeof define&&define.amd?define("unipointer/unipointer",["ev-emitter/ev-emitter"],function(e){return i(t,e)}):"object"==typeof module&&module.exports?module.exports=i(t,require("ev-emitter")):t.Unipointer=i(t,t.EvEmitter)}(window,function(t,i){function e(){}function n(){}var o=n.prototype=Object.create(i.prototype)
+o.bindStartEvent=function(t){this._bindStartEvent(t,!0)},o.unbindStartEvent=function(t){this._bindStartEvent(t,!1)},o._bindStartEvent=function(i,e){e=void 0===e||!!e
+var n=e?"addEventListener":"removeEventListener"
+t.navigator.pointerEnabled?i[n]("pointerdown",this):t.navigator.msPointerEnabled?i[n]("MSPointerDown",this):(i[n]("mousedown",this),i[n]("touchstart",this))},o.handleEvent=function(t){var i="on"+t.type
+this[i]&&this[i](t)},o.getTouch=function(t){for(var i=0;i<t.length;i++){var e=t[i]
+if(e.identifier==this.pointerIdentifier)return e}},o.onmousedown=function(t){var i=t.button
+i&&0!==i&&1!==i||this._pointerDown(t,t)},o.ontouchstart=function(t){this._pointerDown(t,t.changedTouches[0])},o.onMSPointerDown=o.onpointerdown=function(t){this._pointerDown(t,t)},o._pointerDown=function(t,i){this.isPointerDown||(this.isPointerDown=!0,this.pointerIdentifier=void 0!==i.pointerId?i.pointerId:i.identifier,this.pointerDown(t,i))},o.pointerDown=function(t,i){this._bindPostStartEvents(t),this.emitEvent("pointerDown",[t,i])}
+var r={mousedown:["mousemove","mouseup"],touchstart:["touchmove","touchend","touchcancel"],pointerdown:["pointermove","pointerup","pointercancel"],MSPointerDown:["MSPointerMove","MSPointerUp","MSPointerCancel"]}
+return o._bindPostStartEvents=function(i){if(i){var e=r[i.type]
+e.forEach(function(i){t.addEventListener(i,this)},this),this._boundPointerEvents=e}},o._unbindPostStartEvents=function(){this._boundPointerEvents&&(this._boundPointerEvents.forEach(function(i){t.removeEventListener(i,this)},this),delete this._boundPointerEvents)},o.onmousemove=function(t){this._pointerMove(t,t)},o.onMSPointerMove=o.onpointermove=function(t){t.pointerId==this.pointerIdentifier&&this._pointerMove(t,t)},o.ontouchmove=function(t){var i=this.getTouch(t.changedTouches)
+i&&this._pointerMove(t,i)},o._pointerMove=function(t,i){this.pointerMove(t,i)},o.pointerMove=function(t,i){this.emitEvent("pointerMove",[t,i])},o.onmouseup=function(t){this._pointerUp(t,t)},o.onMSPointerUp=o.onpointerup=function(t){t.pointerId==this.pointerIdentifier&&this._pointerUp(t,t)},o.ontouchend=function(t){var i=this.getTouch(t.changedTouches)
+i&&this._pointerUp(t,i)},o._pointerUp=function(t,i){this._pointerDone(),this.pointerUp(t,i)},o.pointerUp=function(t,i){this.emitEvent("pointerUp",[t,i])},o._pointerDone=function(){this.isPointerDown=!1,delete this.pointerIdentifier,this._unbindPostStartEvents(),this.pointerDone()},o.pointerDone=e,o.onMSPointerCancel=o.onpointercancel=function(t){t.pointerId==this.pointerIdentifier&&this._pointerCancel(t,t)},o.ontouchcancel=function(t){var i=this.getTouch(t.changedTouches)
+i&&this._pointerCancel(t,i)},o._pointerCancel=function(t,i){this._pointerDone(),this.pointerCancel(t,i)},o.pointerCancel=function(t,i){this.emitEvent("pointerCancel",[t,i])},n.getPointerPoint=function(t){return{x:t.pageX,y:t.pageY}},n}),function(t,i){"function"==typeof define&&define.amd?define("unidragger/unidragger",["unipointer/unipointer"],function(e){return i(t,e)}):"object"==typeof module&&module.exports?module.exports=i(t,require("unipointer")):t.Unidragger=i(t,t.Unipointer)}(window,function(t,i){function e(){}function n(){}var o=n.prototype=Object.create(i.prototype)
+o.bindHandles=function(){this._bindHandles(!0)},o.unbindHandles=function(){this._bindHandles(!1)}
+var r=t.navigator
+return o._bindHandles=function(t){t=void 0===t||!!t
+var i
+i=r.pointerEnabled?function(i){i.style.touchAction=t?"none":""}:r.msPointerEnabled?function(i){i.style.msTouchAction=t?"none":""}:e
+for(var n=t?"addEventListener":"removeEventListener",o=0;o<this.handles.length;o++){var s=this.handles[o]
+this._bindStartEvent(s,t),i(s),s[n]("click",this)}},o.pointerDown=function(t,i){if("INPUT"==t.target.nodeName&&"range"==t.target.type)return this.isPointerDown=!1,void delete this.pointerIdentifier
+this._dragPointerDown(t,i)
+var e=document.activeElement
+e&&e.blur&&e.blur(),this._bindPostStartEvents(t),this.emitEvent("pointerDown",[t,i])},o._dragPointerDown=function(t,e){this.pointerDownPoint=i.getPointerPoint(e)
+var n=this.canPreventDefaultOnPointerDown(t,e)
+n&&t.preventDefault()},o.canPreventDefaultOnPointerDown=function(t){return"SELECT"!=t.target.nodeName},o.pointerMove=function(t,i){var e=this._dragPointerMove(t,i)
+this.emitEvent("pointerMove",[t,i,e]),this._dragMove(t,i,e)},o._dragPointerMove=function(t,e){var n=i.getPointerPoint(e),o={x:n.x-this.pointerDownPoint.x,y:n.y-this.pointerDownPoint.y}
+return!this.isDragging&&this.hasDragStarted(o)&&this._dragStart(t,e),o},o.hasDragStarted=function(t){return Math.abs(t.x)>3||Math.abs(t.y)>3},o.pointerUp=function(t,i){this.emitEvent("pointerUp",[t,i]),this._dragPointerUp(t,i)},o._dragPointerUp=function(t,i){this.isDragging?this._dragEnd(t,i):this._staticClick(t,i)},o._dragStart=function(t,e){this.isDragging=!0,this.dragStartPoint=i.getPointerPoint(e),this.isPreventingClicks=!0,this.dragStart(t,e)},o.dragStart=function(t,i){this.emitEvent("dragStart",[t,i])},o._dragMove=function(t,i,e){this.isDragging&&this.dragMove(t,i,e)},o.dragMove=function(t,i,e){t.preventDefault(),this.emitEvent("dragMove",[t,i,e])},o._dragEnd=function(t,i){this.isDragging=!1,setTimeout(function(){delete this.isPreventingClicks}.bind(this)),this.dragEnd(t,i)},o.dragEnd=function(t,i){this.emitEvent("dragEnd",[t,i])},o.onclick=function(t){this.isPreventingClicks&&t.preventDefault()},o._staticClick=function(t,i){if(!this.isIgnoringMouseUp||"mouseup"!=t.type){var e=t.target.nodeName
+"INPUT"!=e&&"TEXTAREA"!=e||t.target.focus(),this.staticClick(t,i),"mouseup"!=t.type&&(this.isIgnoringMouseUp=!0,setTimeout(function(){delete this.isIgnoringMouseUp}.bind(this),400))}},o.staticClick=function(t,i){this.emitEvent("staticClick",[t,i])},n.getPointerPoint=i.getPointerPoint,n}),function(t,i){"function"==typeof define&&define.amd?define(["get-size/get-size","unidragger/unidragger"],function(e,n){return i(t,e,n)}):"object"==typeof module&&module.exports?module.exports=i(t,require("get-size"),require("unidragger")):t.Draggabilly=i(t,t.getSize,t.Unidragger)}(window,function(t,i,e){function n(){}function o(t,i){for(var e in i)t[e]=i[e]
+return t}function r(t){return t instanceof HTMLElement}function s(t,i){this.element="string"==typeof t?h.querySelector(t):t,f&&(this.$element=f(this.element)),this.options=o({},this.constructor.defaults),this.option(i),this._create()}function a(t,i,e){return e=e||"round",i?Math[e](t/i)*i:t}var h=t.document,d=t.requestAnimationFrame||t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame,u=0
+d||(d=function(t){var i=(new Date).getTime(),e=Math.max(0,16-(i-u)),n=setTimeout(t,e)
+return u=i+e,n})
+var p=h.documentElement,c="string"==typeof p.style.transform?"transform":"WebkitTransform",f=t.jQuery,g=s.prototype=Object.create(e.prototype)
+return s.defaults={},g.option=function(t){o(this.options,t)},g._create=function(){this.position={},this._getPosition(),this.startPoint={x:0,y:0},this.dragPoint={x:0,y:0},this.startPosition=o({},this.position)
+var t=getComputedStyle(this.element)
+"relative"!=t.position&&"absolute"!=t.position&&(this.element.style.position="relative"),this.enable(),this.setHandles()},g.setHandles=function(){this.handles=this.options.handle?this.element.querySelectorAll(this.options.handle):[this.element],this.bindHandles()},g.dispatchEvent=function(i,e,n){var o=[e].concat(n)
+this.emitEvent(i,o)
+var r=t.jQuery
+if(r&&this.$element)if(e){var s=r.Event(e)
+s.type=i,this.$element.trigger(s,n)}else this.$element.trigger(i,n)},s.prototype._getPosition=function(){var t=getComputedStyle(this.element),i=this._getPositionCoord(t.left,"width"),e=this._getPositionCoord(t.top,"height")
+this.position.x=isNaN(i)?0:i,this.position.y=isNaN(e)?0:e,this._addTransformPosition(t)},s.prototype._getPositionCoord=function(t,e){if(t.indexOf("%")!=-1){var n=i(this.element.parentNode)
+return parseFloat(t)/100*n[e]}return parseInt(t,10)},g._addTransformPosition=function(t){var i=t[c]
+if(0===i.indexOf("matrix")){var e=i.split(","),n=0===i.indexOf("matrix3d")?12:4,o=parseInt(e[n],10),r=parseInt(e[n+1],10)
+this.position.x+=o,this.position.y+=r}},g.pointerDown=function(t,i){this._dragPointerDown(t,i)
+var e=h.activeElement
+e&&e.blur&&e!=h.body&&e.blur(),this._bindPostStartEvents(t),this.element.classList.add("is-pointer-down"),this.dispatchEvent("pointerDown",t,[i])},g.pointerMove=function(t,i){var e=this._dragPointerMove(t,i)
+this.dispatchEvent("pointerMove",t,[i,e]),this._dragMove(t,i,e)},g.dragStart=function(t,i){this.isEnabled&&(this._getPosition(),this.measureContainment(),this.startPosition.x=this.position.x,this.startPosition.y=this.position.y,this.setLeftTop(),this.dragPoint.x=0,this.dragPoint.y=0,this.element.classList.add("is-dragging"),this.dispatchEvent("dragStart",t,[i]),this.animate())},g.measureContainment=function(){var t=this.options.containment
+if(t){var e=r(t)?t:"string"==typeof t?h.querySelector(t):this.element.parentNode,n=i(this.element),o=i(e),s=this.element.getBoundingClientRect(),a=e.getBoundingClientRect(),d=o.borderLeftWidth+o.borderRightWidth,u=o.borderTopWidth+o.borderBottomWidth,p=this.relativeStartPosition={x:s.left-(a.left+o.borderLeftWidth),y:s.top-(a.top+o.borderTopWidth)}
+this.containSize={width:o.width-d-p.x-n.width,height:o.height-u-p.y-n.height}}},g.dragMove=function(t,i,e){if(this.isEnabled){var n=e.x,o=e.y,r=this.options.grid,s=r&&r[0],h=r&&r[1]
+n=a(n,s),o=a(o,h),n=this.containDrag("x",n,s),o=this.containDrag("y",o,h),n="y"==this.options.axis?0:n,o="x"==this.options.axis?0:o,this.position.x=this.startPosition.x+n,this.position.y=this.startPosition.y+o,this.dragPoint.x=n,this.dragPoint.y=o,this.dispatchEvent("dragMove",t,[i,e])}},g.containDrag=function(t,i,e){if(!this.options.containment)return i
+var n="x"==t?"width":"height",o=this.relativeStartPosition[t],r=a(-o,e,"ceil"),s=this.containSize[n]
+return s=a(s,e,"floor"),Math.min(s,Math.max(r,i))},g.pointerUp=function(t,i){this.element.classList.remove("is-pointer-down"),this.dispatchEvent("pointerUp",t,[i]),this._dragPointerUp(t,i)},g.dragEnd=function(t,i){this.isEnabled&&(c&&(this.element.style[c]="",this.setLeftTop()),this.element.classList.remove("is-dragging"),this.dispatchEvent("dragEnd",t,[i]))},g.animate=function(){if(this.isDragging){this.positionDrag()
+var t=this
+d(function(){t.animate()})}},g.setLeftTop=function(){this.element.style.left=this.position.x+"px",this.element.style.top=this.position.y+"px"},g.positionDrag=function(){this.element.style[c]="translate3d( "+this.dragPoint.x+"px, "+this.dragPoint.y+"px, 0)"},g.staticClick=function(t,i){this.dispatchEvent("staticClick",t,[i])},g.enable=function(){this.isEnabled=!0},g.disable=function(){this.isEnabled=!1,this.isDragging&&this.dragEnd()},g.destroy=function(){this.disable(),this.element.style[c]="",this.element.style.left="",this.element.style.top="",this.element.style.position="",this.unbindHandles(),this.$element&&this.$element.removeData("draggabilly")},g._init=n,f&&f.bridget&&f.bridget("draggabilly",s),s})
diff --git a/www/external/gifshot.min.js b/www/external/gifshot.min.js
deleted file mode 100644
index d20775fc..00000000
--- a/www/external/gifshot.min.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/*Copyrights for code authored by Yahoo Inc. is licensed under the following terms:
-MIT License
-Copyright 2015 Yahoo Inc.
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-!function(e,t,r,i){var n,o,a,s,d,c,l,u,m,f,g,h,p,v,b,w,y,C,S,k,F,x;n=function(){var i={URL:e.URL||e.webkitURL||e.mozURL||e.msURL,getUserMedia:function(){var e=r.getUserMedia||r.webkitGetUserMedia||r.mozGetUserMedia||r.msGetUserMedia;return e?e.bind(r):e}(),requestAnimFrame:e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame,requestTimeout:function(e,t){function r(){var i=(new Date).getTime(),s=i-n;s>=t?e.call():o.value=a(r)}if(e=e||i.noop,t=t||0,!i.requestAnimFrame)return setTimeout(e,t);var n=(new Date).getTime(),o=new Object,a=i.requestAnimFrame;return o.value=a(r),o},Blob:e.Blob||e.BlobBuilder||e.WebKitBlobBuilder||e.MozBlobBuilder||e.MSBlobBuilder,btoa:function(){var t=e.btoa||function(e){for(var t,r,i,n,o,a,s,d="",c=0,l=e.length,u="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";l>c;)t=e.charCodeAt(c++),r=e.charCodeAt(c++),i=e.charCodeAt(c++),n=t>>2,o=(3&t)<<4|r>>4,a=(15&r)<<2|i>>6,s=63&i,isNaN(r)?a=s=64:isNaN(i)&&(s=64),d=d+u.charAt(n)+u.charAt(o)+u.charAt(a)+u.charAt(s);return d};return t?t.bind(e):function(){}}(),isObject:function(e){return e&&"[object Object]"===Object.prototype.toString.call(e)},isEmptyObject:function(e){return i.isObject(e)&&!Object.keys(e).length},isArray:function(e){return e&&Array.isArray(e)},isFunction:function(e){return e&&"function"==typeof e},isElement:function(e){return e&&1===e.nodeType},isString:function(e){return"string"==typeof e||"[object String]"===Object.prototype.toString.call(e)},isSupported:{canvas:function(){var e=t.createElement("canvas");return e&&e.getContext&&e.getContext("2d")},webworkers:function(){return e.Worker},blob:function(){return i.Blob},Uint8Array:function(){return e.Uint8Array},Uint32Array:function(){return e.Uint32Array},videoCodecs:function(){var e=t.createElement("video"),r={mp4:!1,h264:!1,ogv:!1,ogg:!1,webm:!1};try{e&&e.canPlayType&&(r.mp4=""!==e.canPlayType('video/mp4; codecs="mp4v.20.8"'),r.h264=""!==(e.canPlayType('video/mp4; codecs="avc1.42E01E"')||e.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')),r.ogv=""!==e.canPlayType('video/ogg; codecs="theora"'),r.ogg=""!==e.canPlayType('video/ogg; codecs="theora"'),r.webm=-1!==e.canPlayType('video/webm; codecs="vp8, vorbis"'))}catch(i){}return r}()},noop:function(){},each:function(e,t){var r,n;if(i.isArray(e))for(r=-1,n=e.length;++r<n&&t(r,e[r])!==!1;);else if(i.isObject(e))for(r in e)if(e.hasOwnProperty(r)&&t(r,e[r])===!1)break},mergeOptions:function n(e,t){if(i.isObject(e)&&i.isObject(t)&&Object.keys){var r={};return i.each(e,function(t){r[t]=e[t]}),i.each(t,function(o){var a=t[o];r[o]=i.isObject(a)?e[o]?n(e[o],a):a:a}),r}},setCSSAttr:function(e,t,r){i.isElement(e)&&(i.isString(t)&&i.isString(r)?e.style[t]=r:i.isObject(t)&&i.each(t,function(t,r){e.style[t]=r}))},removeElement:function(e){i.isElement(e)&&e.parentNode&&e.parentNode.removeChild(e)},createWebWorker:function(e){if(!i.isString(e))return{};try{var t=new i.Blob([e],{type:"text/javascript"}),r=i.URL.createObjectURL(t),n=new Worker(r);return{objectUrl:r,worker:n}}catch(o){return""+o}},getExtension:function(e){return e.substr(e.lastIndexOf(".")+1,e.length)},getFontSize:function(e){if(e=e||{},!t.body||e.resizeFont===!1)return e.fontSize;var r=e.text,i=e.gifWidth,n=parseInt(e.fontSize,10),o=parseInt(e.minFontSize,10),a=t.createElement("div"),s=t.createElement("span");for(a.setAttribute("width",i),a.appendChild(s),s.innerHTML=r,s.style.fontSize=n+"px",s.style.textIndent="-9999px",s.style.visibility="hidden",t.body.appendChild(s);s.offsetWidth>i&&n>=o;)s.style.fontSize=--n+"px";return t.body.removeChild(s),n+"px"},webWorkerError:!1};return i}(),o=function(e){var t={validate:function(r){r=e.isObject(r)?r:{};var i={};return e.each(t.validators,function(e,t){var n=t.errorCode;return r[n]||t.condition?void 0:(i=t,i.error=!0,!1)}),delete i.condition,i},isValid:function(e){var r=t.validate(e),i=r.error!==!0?!0:!1;return i},validators:[{condition:e.isFunction(e.getUserMedia),errorCode:"getUserMedia",errorMsg:"The getUserMedia API is not supported in your browser"},{condition:e.isSupported.canvas(),errorCode:"canvas",errorMsg:"Canvas elements are not supported in your browser"},{condition:e.isSupported.webworkers(),errorCode:"webworkers",errorMsg:"The Web Workers API is not supported in your browser"},{condition:e.isFunction(e.URL),errorCode:"window.URL",errorMsg:"The window.URL API is not supported in your browser"},{condition:e.isSupported.blob(),errorCode:"window.Blob",errorMsg:"The window.Blob File API is not supported in your browser"},{condition:e.isSupported.Uint8Array(),errorCode:"window.Uint8Array",errorMsg:"The window.Uint8Array function constructor is not supported in your browser"},{condition:e.isSupported.Uint32Array(),errorCode:"window.Uint32Array",errorMsg:"The window.Uint32Array function constructor is not supported in your browser"}],messages:{videoCodecs:{errorCode:"videocodec",errorMsg:"The video codec you are trying to use is not supported in your browser"}}};return t}(n),a={sampleInterval:10,numWorkers:2,gifWidth:200,gifHeight:200,interval:.1,numFrames:10,keepCameraOn:!1,images:[],video:null,webcamVideoElement:null,cameraStream:null,text:"",fontWeight:"normal",fontSize:"16px",minFontSize:"10px",resizeFont:!1,fontFamily:"sans-serif",fontColor:"#ffffff",textAlign:"center",textBaseline:"bottom",textXCoordinate:null,textYCoordinate:null,progressCallback:function(){},completeCallback:function(){},saveRenderingContexts:!1,savedRenderingContexts:[],crossOrigin:"Anonymous"},s=function(){return o.isValid()},d=function(){return o.isValid()},c=function(){var e={getUserMedia:!0};return o.isValid(e)},l=function(e){var t=!1;if(n.isArray(e)&&e.length){if(n.each(e,function(e,r){n.isSupported.videoCodecs[r]&&(t=!0)}),!t)return!1}else if(n.isString(e)&&e.length&&!n.isSupported.videoCodecs[e])return!1;return o.isValid({getUserMedia:!0})},u=function(){function e(){function e(e,t,r){var i,n;for(u=e,m=t,f=r,g=new Array(h),i=0;h>i;i++)g[i]=new Array(4),n=g[i],n[0]=n[1]=n[2]=(i<<S+8)/h|0,D[i]=x/h|0,G[i]=0}function t(){for(var e=[],t=new Array(h),r=0;h>r;r++)t[g[r][3]]=r;for(var i=0,n=0;h>n;n++){var o=t[n];e[i++]=g[o][0],e[i++]=g[o][1],e[i++]=g[o][2]}return e}function r(){var e,t,r,i,n,o,a,s;for(a=0,s=0,e=0;h>e;e++){for(n=g[e],r=e,i=n[1],t=e+1;h>t;t++)o=g[t],o[1]<i&&(r=t,i=o[1]);if(o=g[r],e!=r&&(t=o[0],o[0]=n[0],n[0]=t,t=o[1],o[1]=n[1],n[1]=t,t=o[2],o[2]=n[2],n[2]=t,t=o[3],o[3]=n[3],n[3]=t),i!=a){for(B[a]=s+e>>1,t=a+1;i>t;t++)B[t]=e;a=i,s=e}}for(B[a]=s+C>>1,t=a+1;256>t;t++)B[t]=C}function i(){var e,t,r,i,n,o,a,g,h,C,F,x,E,W;for(y>m&&(f=1),l=30+(f-1)/3,x=u,E=0,W=m,F=m/(3*f),C=F/k|0,g=j,o=I,a=o>>R,1>=a&&(a=0),e=0;a>e;e++)q[e]=g*((a*a-e*e)*z/(a*a));for(h=y>m?3:m%p!==0?3*p:m%v!==0?3*v:m%b!==0?3*b:3*w,e=0;F>e;)if(r=(255&x[E+0])<<S,i=(255&x[E+1])<<S,n=(255&x[E+2])<<S,t=c(r,i,n),d(g,t,r,i,n),0!==a&&s(a,t,r,i,n),E+=h,E>=W&&(E-=m),e++,0===C&&(C=1),e%C===0)for(g-=g/l,o-=o/T,a=o>>R,1>=a&&(a=0),t=0;a>t;t++)q[t]=g*((a*a-t*t)*z/(a*a))}function n(e,t,r){var i,n,o,a,s,d,c;for(s=1e3,c=-1,i=B[t],n=i-1;h>i||n>=0;)h>i&&(d=g[i],o=d[1]-t,o>=s?i=h:(i++,0>o&&(o=-o),a=d[0]-e,0>a&&(a=-a),o+=a,s>o&&(a=d[2]-r,0>a&&(a=-a),o+=a,s>o&&(s=o,c=d[3])))),n>=0&&(d=g[n],o=t-d[1],o>=s?n=-1:(n--,0>o&&(o=-o),a=d[0]-e,0>a&&(a=-a),o+=a,s>o&&(a=d[2]-r,0>a&&(a=-a),o+=a,s>o&&(s=o,c=d[3]))));return c}function o(){return i(),a(),r(),t()}function a(){var e;for(e=0;h>e;e++)g[e][0]>>=S,g[e][1]>>=S,g[e][2]>>=S,g[e][3]=e}function s(e,t,r,i,n){var o,a,s,d,c,l,u;for(s=t-e,-1>s&&(s=-1),d=t+e,d>h&&(d=h),o=t+1,a=t-1,l=1;d>o||a>s;){if(c=q[l++],d>o){u=g[o++];try{u[0]-=c*(u[0]-r)/P|0,u[1]-=c*(u[1]-i)/P|0,u[2]-=c*(u[2]-n)/P|0}catch(m){}}if(a>s){u=g[a--];try{u[0]-=c*(u[0]-r)/P|0,u[1]-=c*(u[1]-i)/P|0,u[2]-=c*(u[2]-n)/P|0}catch(m){}}}}function d(e,t,r,i,n){var o=g[t],a=e/j;o[0]-=a*(o[0]-r)|0,o[1]-=a*(o[1]-i)|0,o[2]-=a*(o[2]-n)|0}function c(e,t,r){var i,n,o,a,s,d,c,l,u,m;for(l=~(1<<31),u=l,d=-1,c=d,i=0;h>i;i++)m=g[i],n=m[0]-e,0>n&&(n=-n),o=m[1]-t,0>o&&(o=-o),n+=o,o=m[2]-r,0>o&&(o=-o),n+=o,l>n&&(l=n,d=i),a=n-(G[i]>>F-S),u>a&&(u=a,c=i),s=D[i]>>W,D[i]-=s,G[i]+=s<<E;return D[d]+=O,G[d]-=A,c}var l,u,m,f,g,h=256,p=499,v=491,b=487,w=503,y=3*w,C=h-1,S=4,k=100,F=16,x=1<<F,E=10,W=10,O=x>>W,A=x<<E-W,U=h>>3,R=6,M=1<<R,I=U*M,T=30,V=10,j=1<<V,H=8,z=1<<H,L=V+H,P=1<<L,B=[],G=[],D=[],q=[];e.apply(this,arguments);var N={};return N.map=n,N.process=o,N}return e}(),m=function(e){var t=function(){try{self.onmessage=function(e){var t,i=e.data||{};i.gifshot&&(t=r.run(i),postMessage(t))}}catch(t){}var r={dataToRGB:function(e,t,r){for(var i=0,n=t*r*4,o=[];n>i;)o.push(e[i++]),o.push(e[i++]),o.push(e[i++]),i++;return o},componentizedPaletteToArray:function(e){var t,r,i,n,o=[];for(t=0;t<e.length;t+=3)r=e[t],i=e[t+1],n=e[t+2],o.push(r<<16|i<<8|n);return o},processFrameWithQuantizer:function(t,r,i,n){var o,a,s,d,c=this.dataToRGB(t,r,i),l=new e(c,c.length,n),u=l.process(),m=new Uint32Array(this.componentizedPaletteToArray(u)),f=r*i,g=new Uint8Array(f),h=0;for(o=0;f>o;o++)a=c[h++],s=c[h++],d=c[h++],g[o]=l.map(a,s,d);return{pixels:g,palette:m}},run:function(e){var t=e.width,r=e.height,i=e.data,n=(e.palette,e.sampleInterval);return this.processFrameWithQuantizer(i,t,r,n)}};return r};return t}(u),f=function(e,t,r,n){function o(e){var t=e.length;if(2>t||t>256||t&t-1)throw"Invalid code/color length, must be power of 2 and 2 .. 256.";return t}function a(e,t,r,n){function o(r){for(;f>=r;)e[t++]=255&g,g>>=8,f-=8,t===s+256&&(e[s]=255,s=t++)}function a(e){g|=e<<f,f+=m,o(8)}e[t++]=r;var s=t++,d=1<<r,c=d-1,l=d+1,u=l+1,m=r+1,f=0,g=0,h=n[0]&c,p={};a(d);for(var v=1,b=n.length;b>v;++v){var w=n[v]&c,y=h<<8|w,C=p[y];if(C===i){for(g|=h<<f,f+=m;f>=8;)e[t++]=255&g,g>>=8,f-=8,t===s+256&&(e[s]=255,s=t++);4096===u?(a(d),u=l+1,m=r+1,p={}):(u>=1<<m&&++m,p[y]=u++),h=w}else h=C}return a(h),a(l),o(1),s+1===t?e[s]=0:(e[s]=t-s-1,e[t++]=0),t}var s=0;n=n===i?{}:n;var d=n.loop===i?null:n.loop,c=n.palette===i?null:n.palette;if(0>=t||0>=r||t>65535||r>65535)throw"Width/Height invalid.";e[s++]=71,e[s++]=73,e[s++]=70,e[s++]=56,e[s++]=57,e[s++]=97;var l=0,u=0;if(e[s++]=255&t,e[s++]=t>>8&255,e[s++]=255&r,e[s++]=r>>8&255,e[s++]=(null!==c?128:0)|l,e[s++]=u,e[s++]=0,null!==d){if(0>d||d>65535)throw"Loop count invalid.";e[s++]=33,e[s++]=255,e[s++]=11,e[s++]=78,e[s++]=69,e[s++]=84,e[s++]=83,e[s++]=67,e[s++]=65,e[s++]=80,e[s++]=69,e[s++]=50,e[s++]=46,e[s++]=48,e[s++]=3,e[s++]=1,e[s++]=255&d,e[s++]=d>>8&255,e[s++]=0}var m=!1;this.addFrame=function(t,r,n,d,l,u){if(m===!0&&(--s,m=!1),u=u===i?{}:u,0>t||0>r||t>65535||r>65535)throw"x/y invalid.";if(0>=n||0>=d||n>65535||d>65535)throw"Width/Height invalid.";if(l.length<n*d)throw"Not enough pixels for the frame size.";var f=!0,g=u.palette;if((g===i||null===g)&&(f=!1,g=c),g===i||null===g)throw"Must supply either a local or global palette.";for(var h=o(g),p=0;h>>=1;)++p;h=1<<p;var v=u.delay===i?0:u.delay,b=u.disposal===i?0:u.disposal;if(0>b||b>3)throw"Disposal out of range.";var w=!1,y=0;if(u.transparent!==i&&null!==u.transparent&&(w=!0,y=u.transparent,0>y||y>=h))throw"Transparent color index.";if((0!==b||w||0!==v)&&(e[s++]=33,e[s++]=249,e[s++]=4,e[s++]=b<<2|(w===!0?1:0),e[s++]=255&v,e[s++]=v>>8&255,e[s++]=y,e[s++]=0),e[s++]=44,e[s++]=255&t,e[s++]=t>>8&255,e[s++]=255&r,e[s++]=r>>8&255,e[s++]=255&n,e[s++]=n>>8&255,e[s++]=255&d,e[s++]=d>>8&255,e[s++]=f===!0?128|p-1:0,f===!0)for(var C=0,S=g.length;S>C;++C){var k=g[C];e[s++]=k>>16&255,e[s++]=k>>8&255,e[s++]=255&k}s=a(e,s,2>p?2:p,l)},this.end=function(){return m===!1&&(e[s++]=59,m=!0),s}},g=function(e,r,i,n){var o=function(t){this.canvas=null,this.ctx=null,this.repeat=0,this.frames=[],this.numRenderedFrames=0,this.onRenderCompleteCallback=e.noop,this.onRenderProgressCallback=e.noop,this.workers=[],this.availableWorkers=[],this.generatingGIF=!1,this.options=t,this.initializeWebWorkers(t)};return o.prototype={workerMethods:r(),initializeWebWorkers:function(n){var o,a,s,d,c=i.toString()+"("+r.toString()+"());",l=-1,u="";for(d=n.numWorkers;++l<d;)o=e.createWebWorker(c),e.isObject(o)?(a=o.objectUrl,s=o.worker,this.workers.push({worker:s,objectUrl:a}),this.availableWorkers.push(s)):(u=o,e.webWorkerError=!!o);this.workerError=u,this.canvas=t.createElement("canvas"),this.canvas.width=n.gifWidth,this.canvas.height=n.gifHeight,this.ctx=this.canvas.getContext("2d"),this.frames=[]},getWorker:function(){return this.availableWorkers.pop()},freeWorker:function(e){this.availableWorkers.push(e)},byteMap:function(){for(var e=[],t=0;256>t;t++)e[t]=String.fromCharCode(t);return e}(),bufferToString:function(e){for(var t=e.length,r="",i=-1;++i<t;)r+=this.byteMap[e[i]];return r},onFrameFinished:function(t){var r=this,i=r.frames,n=r.options;hasExistingImages=!!(n.images||[]).length,allDone=i.every(function(e){return!e.beingProcessed&&e.done}),r.numRenderedFrames++,hasExistingImages&&t(r.numRenderedFrames/i.length),r.onRenderProgressCallback(.75*r.numRenderedFrames/i.length),allDone?r.generatingGIF||r.generateGIF(i,r.onRenderCompleteCallback):e.requestTimeout(function(){r.processNextFrame()},1)},processFrame:function(e){var t,r,i=this,n=this.options,o=n.progressCallback,a=n.sampleInterval,s=this.frames,d=function(e){var n=e.data;delete t.data,t.pixels=Array.prototype.slice.call(n.pixels),t.palette=Array.prototype.slice.call(n.palette),t.done=!0,t.beingProcessed=!1,i.freeWorker(r),i.onFrameFinished(o)};return t=s[e],t.beingProcessed||t.done?(this.onFrameFinished(),void 0):(t.sampleInterval=a,t.beingProcessed=!0,t.gifshot=!0,r=this.getWorker(),r?(r.onmessage=d,r.postMessage(t)):d({data:i.workerMethods.run(t)}),void 0)},startRendering:function(e){this.onRenderCompleteCallback=e;for(var t=0;t<this.options.numWorkers&&t<this.frames.length;t++)this.processFrame(t)},processNextFrame:function(){for(var e=-1,t=0;t<this.frames.length;t++){var r=this.frames[t];if(!r.done&&!r.beingProcessed){e=t;break}}e>=0&&this.processFrame(e)},generateGIF:function(t,r){var i,o,a=[],s={loop:this.repeat},d=this.options,c=d.interval,l=d.images,u=!!l.length,m=d.gifHeight,f=d.gifWidth,g=new n(a,f,m,s),h=this.onRenderProgressCallback,p=u?100*c:0;this.generatingGIF=!0,e.each(t,function(e,r){var i=r.palette;h(.75+.25*r.position*1/t.length),g.addFrame(0,0,f,m,r.pixels,{palette:i,delay:p})}),g.end(),h(1),this.frames=[],this.generatingGIF=!1,e.isFunction(r)&&(i=this.bufferToString(a),o="data:image/gif;base64,"+e.btoa(i),r(o))},setRepeat:function(e){this.repeat=e},addFrame:function(t,r){r=e.isObject(r)?r:{};var i,n=this,o=n.ctx,a=n.options,s=a.gifWidth,d=a.gifHeight,c=(r.gifHeight,r.gifWidth,r.text),l=r.fontWeight,u=e.getFontSize(r),m=r.fontFamily,f=r.fontColor,g=r.textAlign,h=r.textBaseline,p=r.textXCoordinate?r.textXCoordinate:"left"===g?1:"right"===g?s:s/2,v=r.textYCoordinate?r.textYCoordinate:"top"===h?1:"center"===h?d/2:d,b=l+" "+u+" "+m;try{o.drawImage(t,0,0,s,d),c&&(o.font=b,o.fillStyle=f,o.textAlign=g,o.textBaseline=h,o.fillText(c,p,v)),i=o.getImageData(0,0,s,d),n.addFrameImageData(i)}catch(w){return""+w}},addFrameImageData:function(e){var t=this.frames,r=e.data;this.frames.push({data:r,width:e.width,height:e.height,palette:null,dithering:null,done:!1,beingProcessed:!1,position:t.length})},onRenderProgress:function(e){this.onRenderProgressCallback=e},isRendering:function(){return this.generatingGIF},getBase64GIF:function(t){var r=this,i=function(i){r.destroyWorkers(),e.requestTimeout(function(){t(i)},0)};r.startRendering(i)},destroyWorkers:function(){if(!this.workerError){var t=this.workers;e.each(t,function(t,r){var i=r.worker,n=r.objectUrl;i.terminate(),e.URL.revokeObjectURL(n)})}}},o}(n,m,u,f),h=function(e,t){e.getBase64GIF(function(e){t({error:!1,errorCode:"",errorMsg:"",image:e})})},p=function(e){function r(){n.each(p,function(e,t){t&&s.addFrame(t,u)}),h(s,l)}var a,s,d=e.images,c=e.imagesLength,l=e.callback,u=e.options,m={getUserMedia:!0,"window.URL":!0},f=o.validate(m),p=[],v=0;return f.error?l(f):(s=new g(u),n.each(d,function(e,o){n.isElement(o)?(u.crossOrigin&&(o.crossOrigin=u.crossOrigin),p[e]=o,v+=1,v===c&&r()):n.isString(o)&&(a=t.createElement("img"),u.crossOrigin&&(a.crossOrigin=u.crossOrigin),a.onerror=function(){p.length>e&&(p[e]=i)}(function(t){t.onload=function(){p[e]=t,v+=1,v===c&&r(),n.removeElement(t)}}(a)),a.src=o,n.setCSSAttr(a,{position:"fixed",opacity:"0"}),t.body.appendChild(a))}),void 0)},v={getGIF:function(e,r){r=n.isFunction(r)?r:n.noop;var i,o=t.createElement("canvas"),a=e.images,s=!!a.length,d=e.videoElement,c=e.keepCameraOn,l=e.webcamVideoElement,u=e.cameraStream,m=+e.gifWidth,f=+e.gifHeight,h=e.videoWidth,p=e.videoHeight,v=(+e.sampleInterval,+e.numWorkers,e.crop),b=+e.interval,w=s?0:1e3*b,y=e.progressCallback,C=e.savedRenderingContexts,S=e.saveRenderingContexts,k=[],F=C.length?C.length:e.numFrames,x=F,E=new g(e),W=e.text,O=e.fontWeight,A=n.getFontSize(e),U=e.fontFamily,R=e.fontColor,M=e.textAlign,I=e.textBaseline,T=e.textXCoordinate?e.textXCoordinate:"left"===M?1:"right"===M?m:m/2,V=e.textYCoordinate?e.textYCoordinate:"top"===I?1:"center"===I?f/2:f,j=O+" "+A+" "+U,H=v?Math.floor(v.scaledWidth/2):0,z=v?h-v.scaledWidth:0,L=v?Math.floor(v.scaledHeight/2):0,P=v?p-v.scaledHeight:0,B=function G(){function e(){try{z>h&&(z=h),P>p&&(P=p),0>H&&(H=0),0>L&&(L=0),i.drawImage(d,H,L,z,P,0,0,m,f),t()}catch(r){if("NS_ERROR_NOT_AVAILABLE"!==r.name)throw r;n.requestTimeout(e,100)}}function t(){x=o;var t,a,s,g,h=F-x;S&&k.push(i.getImageData(0,0,m,f)),W&&(i.font=j,i.fillStyle=R,i.textAlign=M,i.textBaseline=I,i.fillText(W,T,V)),t=i.getImageData(0,0,m,f),a=t.data,s=a[0]+a[1]+a[2]+a[3],g=0===s,g?1===h&&1===F&&e():E.addFrameImageData(t),y(h/F),o>0&&n.requestTimeout(G,w),x||E.getBase64GIF(function(e){r({error:!1,errorCode:"",errorMsg:"",image:e,cameraStream:u,videoElement:d,webcamVideoElement:l,savedRenderingContexts:k,keepCameraOn:c})})}var o=x-1;C.length?(i.putImageData(C[F-x],0,0),t()):e()};F=null!=F?F:10,b=null!=b?b:.1,o.width=m,o.height=f,i=o.getContext("2d"),function D(){return C.length||0!==d.currentTime?(B(),void 0):(n.requestTimeout(D,100),void 0)}()},getCropDimensions:function(e){var t=e.videoWidth,r=e.videoHeight,i=e.gifWidth,n=e.gifHeight,o={width:0,height:0,scaledWidth:0,scaledHeight:0};return t>r?(o.width=Math.round(t*(n/r))-i,o.scaledWidth=Math.round(o.width*(r/n))):(o.height=Math.round(r*(i/t))-n,o.scaledHeight=Math.round(o.height*(t/i))),o}},b={loadedData:!1,defaultVideoDimensions:{width:640,height:480},findVideoSize:function E(e){E.attempts=E.attempts||0;var t=this,r=e.videoElement,i=e.cameraStream,o=e.completedCallback;r&&(r.videoWidth>0&&r.videoHeight>0?(r.removeEventListener("loadeddata",t.findVideoSize),o({videoElement:r,cameraStream:i,videoWidth:r.videoWidth,videoHeight:r.videoHeight})):E.attempts<10?(E.attempts+=1,n.requestTimeout(function(){t.findVideoSize(e)},200)):o({videoElement:r,cameraStream:i,videoWidth:t.defaultVideoDimensions.width,videoHeight:t.defaultVideoDimensions.height}))},onStreamingTimeout:function(e){n.isFunction(e)&&e({error:!0,errorCode:"getUserMedia",errorMsg:"There was an issue with the getUserMedia API - Timed out while trying to start streaming",image:null,cameraStream:{}})},stream:function(e){var t=this,r=n.isArray(e.existingVideo)?e.existingVideo[0]:e.existingVideo,i=e.videoElement,o=e.cameraStream,a=e.streamedCallback,s=e.completedCallback;n.isFunction(a)&&a(),r?n.isString(r)&&(i.src=r,i.innerHTML='<source src="'+r+'" type="video/'+n.getExtension(r)+'" />'):i.mozSrcObject?i.mozSrcObject=o:n.URL&&(i.src=n.URL.createObjectURL(o)),i.play(),n.requestTimeout(function d(){d.count=d.count||0,t.loadedData===!0?(t.findVideoSize({videoElement:i,cameraStream:o,completedCallback:s}),t.loadedData=!1):(d.count+=1,d.count>10?t.findVideoSize({videoElement:i,cameraStream:o,completedCallback:s}):d())},100)},startStreaming:function(e){var r=this,i=n.isFunction(e.error)?e.error:n.noop,o=n.isFunction(e.streamed)?e.streamed:n.noop,a=n.isFunction(e.completed)?e.completed:n.noop,s=e.existingVideo,d=e.webcamVideoElement,c=n.isElement(s)?s:d?d:t.createElement("video"),l=e.lastCameraStream,u=e.crossOrigin,m=e.options;u&&(c.crossOrigin=m.crossOrigin),c.autoplay=!0,c.loop=!0,c.muted=!0,c.addEventListener("loadeddata",function(){r.loadedData=!0}),s?r.stream({videoElement:c,existingVideo:s,completedCallback:a}):l?r.stream({videoElement:c,cameraStream:l,streamedCallback:o,completedCallback:a}):n.getUserMedia({video:!0},function(e){r.stream({videoElement:c,cameraStream:e,streamedCallback:o,completedCallback:a})},i)},startVideoStreaming:function(e,t){t=t||{};var r,o=this,a=t.timeout!==i?t.timeout:0,s=t.callback,d=t.webcamVideoElement;a>0&&(r=n.requestTimeout(function(){o.onStreamingTimeout(s)},1e4)),this.startStreaming({error:function(){s({error:!0,errorCode:"getUserMedia",errorMsg:"There was an issue with the getUserMedia API - the user probably denied permission",image:null,cameraStream:{}})},streamed:function(){clearTimeout(r)},completed:function(t){var r=t.cameraStream,i=t.videoElement,n=t.videoWidth,o=t.videoHeight;e({cameraStream:r,videoElement:i,videoWidth:n,videoHeight:o})},lastCameraStream:t.lastCameraStream,webcamVideoElement:d,crossOrigin:t.crossOrigin,options:t})},stopVideoStreaming:function(e){e=n.isObject(e)?e:{};var t=e.cameraStream,r=e.videoElement,i=e.keepCameraOn,o=e.webcamVideoElement;!i&&t&&n.isFunction(t.stop)&&t.stop(),n.isElement(r)&&!o&&(r.pause(),n.isFunction(n.URL.revokeObjectURL)&&!n.webWorkerError&&r.src&&n.URL.revokeObjectURL(r.src),n.removeElement(r))}},w=function(e){e=n.isObject(e)?e:{};var t=(n.isObject(e.options)?e.options:{},e.cameraStream),r=e.videoElement,i=e.webcamVideoElement,o=e.keepCameraOn;b.stopVideoStreaming({cameraStream:t,videoElement:r,keepCameraOn:o,webcamVideoElement:i})},y=function(e,r){var i=e.options||{},o=i.images,a=i.video,s=(+i.numFrames,e.cameraStream),d=e.videoElement,c=e.videoWidth,l=e.videoHeight,u=+i.gifWidth,m=+i.gifHeight,f=v.getCropDimensions({videoWidth:c,videoHeight:l,gifHeight:m,gifWidth:u}),g=r;i.crop=f,i.videoElement=d,i.videoWidth=c,i.videoHeight=l,i.cameraStream=s,n.isElement(d)&&(d.width=u+f.width,d.height=m+f.height,i.webcamVideoElement||(n.setCSSAttr(d,{position:"fixed",opacity:"0"}),t.body.appendChild(d)),d.play(),v.getGIF(i,function(e){o&&o.length||a&&a.length||w(e),g(e)}))},C=function(e){var t,r,i=e.existingVideo,a=e.callback,s=e.options,d={getUserMedia:!0,"window.URL":!0},c=o.validate(d);if(c.error)return a(c);if(n.isElement(i)&&i.src){if(r=i.src,t=n.getExtension(r),!n.isSupported.videoCodecs[t])return a(o.messages.videoCodecs)}else n.isArray(i)&&n.each(i,function(e,r){return t=r.substr(r.lastIndexOf(".")+1,r.length),n.isSupported.videoCodecs[t]?(i=r,!1):void 0});b.startStreaming({completed:function(e){e.options=s||{},y(e,a)},existingVideo:i,crossOrigin:s.crossOrigin,options:s})},S=function(e){var t=e.lastCameraStream,r=e.callback,i=e.webcamVideoElement,n=e.options;return d()?n.savedRenderingContexts.length?(v.getWebcamGIF(n,function(e){r(e)}),void 0):(b.startVideoStreaming(function(e){e.options=n||{},y(e,r)},{lastCameraStream:t,callback:r,webcamVideoElement:i,crossOrigin:n.crossOrigin}),void 0):r(o.validate())},k=function(e,t){if(t=n.isFunction(e)?e:t,e=n.isObject(e)?e:{},n.isFunction(t)){var r=n.mergeOptions(a,e)||{},i=e.cameraStream,o=r.images,s=o?o.length:0,d=r.video,c=r.webcamVideoElement;r=n.mergeOptions(r,{gifWidth:Math.floor(r.gifWidth),gifHeight:Math.floor(r.gifHeight)}),s?p({images:o,imagesLength:s,callback:t,options:r}):d?C({existingVideo:d,callback:t,options:r}):S({lastCameraStream:i,callback:t,webcamVideoElement:c,options:r})}},F=function(e,t){if(t=n.isFunction(e)?e:t,e=n.isObject(e)?e:{},n.isFunction(t)){var r=n.mergeOptions(a,e),i=n.mergeOptions(r,{interval:.1,numFrames:1,gifWidth:Math.floor(r.gifWidth),gifHeight:Math.floor(r.gifHeight)});k(i,t)}},x=function(e,t,r,i,n,o,a,s,d,c){var l={utils:e,error:t,defaultOptions:r,createGIF:s,takeSnapShot:d,stopVideoStreaming:c,isSupported:i,isWebCamGIFSupported:n,isExistingVideoGIFSupported:a,isExistingImagesGIFSupported:o,VERSION:"0.3.2"};return l}(n,o,a,s,d,c,l,k,F,w),function(t){"function"==typeof define&&define.amd?define([],function(){return t}):"undefined"!=typeof exports?module.exports=t:e.gifshot=t}(x)}("undefined"!=typeof window?window:{},"undefined"!=typeof document?document:{createElement:function(){}},"undefined"!=typeof window?window.navigator:{}); \ No newline at end of file
diff --git a/www/external/gifwriter.min.js b/www/external/gifwriter.min.js
new file mode 100644
index 00000000..427fd50f
--- /dev/null
+++ b/www/external/gifwriter.min.js
@@ -0,0 +1,64 @@
+// (c) Dean McNamee <dean@gmail.com>, 2013.
+// //
+// // https://github.com/deanm/omggif
+// //
+// // 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.
+// //
+// // omggif is a JavaScript implementation of a GIF 89a encoder and decoder,
+// // including animation and compression. It does not rely on any specific
+// // underlying system, so should run in the browser, Node, or Plask.
+// Main compression routine, palette indexes -> LZW code stream.
+// |index_stream| must have at least one entry.
+"use strict"
+function _classCallCheck(r,e){if(!(r instanceof e))throw new TypeError("Cannot call a class as a function")}function check_palette_and_num_colors(r){var e=r.length
+if(e<2||e>256||e&e-1)throw new Error("Invalid code/color length, must be power of 2 and 2 .. 256.")
+return e}function GifWriterOutputLZWCodeStream(r,e,t,a){function n(t){for(;s>=t;)r[e++]=255&v,v>>=8,s-=8,e===i+256&&(r[i]=255,i=e++)}function o(r){v|=r<<s,s+=c,n(8)}r[e++]=t
+var i=e++,l=1<<t,u=l-1,f=l+1,d=f+1,c=t+1,s=0,v=0,h=a[0]&u,p={}
+o(l)
+for(var w=1,g=a.length;w<g;++w){var _=a[w]&u,y=h<<8|_,m=p[y]
+if(void 0===m){for(v|=h<<s,s+=c;s>=8;)r[e++]=255&v,v>>=8,s-=8,e===i+256&&(r[i]=255,i=e++)
+4096===d?(o(l),d=f+1,c=t+1,p={}):(d>=1<<c&&++c,p[y]=d++),h=_}else h=m}return o(h),o(f),n(1),i+1===e?r[i]=0:(r[i]=e-i-1,r[e++]=0),e}var GifWriter=function(){function r(e,t,a){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{}
+_classCallCheck(this,r)
+var o=n.loop,i=n.palette,l=0,u=[],f=i
+if(t<=0||a<=0||t>65535||a>65535)throw new Error("Width/Height invalid.")
+u[l++]=71,u[l++]=73,u[l++]=70,u[l++]=56,u[l++]=57,u[l++]=97
+var d=0,c=0
+if(f){for(var s=check_palette_and_num_colors(f);s>>=1;)++d
+if(s=1<<d,d--,void 0!==n.background){if(c=n.background,c>=s)throw new Error("Background index out of range.")
+if(0===c)throw new Error("Background index explicitly passed as 0.")}}if(u[l++]=255&t,u[l++]=t>>8&255,u[l++]=255&a,u[l++]=a>>8&255,u[l++]=(f?128:0)|d,u[l++]=c,u[l++]=0,f)for(var v=f,h=Array.isArray(v),p=0,v=h?v:v[Symbol.iterator]();;){var w
+if(h){if(p>=v.length)break
+w=v[p++]}else{if(p=v.next(),p.done)break
+w=p.value}var g=w
+u[l++]=g>>16&255,u[l++]=g>>8&255,u[l++]=255&g}if(Number.isInteger(o)){if(o<0||o>65535)throw"Loop count invalid."
+u[l++]=33,u[l++]=255,u[l++]=11,u[l++]=78,u[l++]=69,u[l++]=84,u[l++]=83,u[l++]=67,u[l++]=65,u[l++]=80,u[l++]=69,u[l++]=50,u[l++]=46,u[l++]=48,u[l++]=3,u[l++]=1,u[l++]=255&o,u[l++]=o>>8&255,u[l++]=0}var _=this,y=e.getReader()
+return new ReadableStream({start:function(r){r.enqueue(new Uint8Array(u))},pull:function(r){return y.read().then(function(e){var t=e.done,a=e.value
+return t?(r.enqueue(new Uint8Array([59])),void r.close()):void _.addFrame.apply(_,[r].concat(a))})}})}return r.prototype.addFrame=function(r,e,t,a,n,o){var i=arguments.length>6&&void 0!==arguments[6]?arguments[6]:{},l=0,u=[]
+if(e<0||t<0||e>65535||t>65535)throw new Error("x/y invalid.")
+if(a<=0||n<=0||a>65535||n>65535)throw"Width/Height invalid."
+if(o.length<a*n)throw"Not enough pixels for the frame size."
+var f=!0,d=i.palette
+if(void 0!==d&&null!==d||(f=!1,d=global_palette),void 0===d||null===d)throw"Must supply either a local or global palette."
+for(var c=check_palette_and_num_colors(d),s=0;c>>=1;)++s
+c=1<<s
+var v=void 0===i.delay?0:i.delay,h=void 0===i.disposal?0:i.disposal
+if(h<0||h>3)throw"Disposal out of range."
+var p=!1,w=0
+if(void 0!==i.transparent&&null!==i.transparent&&(p=!0,w=i.transparent,w<0||w>=c))throw"Transparent color index."
+if((0!==h||p||0!==v)&&(u[l++]=33,u[l++]=249,u[l++]=4,u[l++]=h<<2|(p===!0?1:0),u[l++]=255&v,u[l++]=v>>8&255,u[l++]=w,u[l++]=0),u[l++]=44,u[l++]=255&e,u[l++]=e>>8&255,u[l++]=255&t,u[l++]=t>>8&255,u[l++]=255&a,u[l++]=a>>8&255,u[l++]=255&n,u[l++]=n>>8&255,u[l++]=f===!0?128|s-1:0,f===!0)for(var g=0,_=d.length;g<_;++g){var y=d[g]
+u[l++]=y>>16&255,u[l++]=y>>8&255,u[l++]=255&y}GifWriterOutputLZWCodeStream(u,l,s<2?2:s,o),r.enqueue(new Uint8Array(u))},r}()
diff --git a/www/external/imagesloaded.pkgd.min.js b/www/external/imagesloaded.pkgd.min.js
new file mode 100644
index 00000000..aa190be5
--- /dev/null
+++ b/www/external/imagesloaded.pkgd.min.js
@@ -0,0 +1,42 @@
+/*!
+ * imagesLoaded PACKAGED v4.1.0
+ * JavaScript is all like "You images are done yet or what?"
+ * MIT License
+ */
+!function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}(this,function(){function t(){}var e=t.prototype
+return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[]
+return n.indexOf(e)==-1&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e)
+var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||[]
+return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t]
+if(i&&i.length){var n=i.indexOf(e)
+return n!=-1&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t]
+if(i&&i.length){var n=0,o=i[n]
+e=e||[]
+for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o]
+s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){"use strict"
+"function"==typeof define&&define.amd?define(["ev-emitter/ev-emitter"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}(window,function(t,e){function i(t,e){for(var i in e)t[i]=e[i]
+return t}function n(t){var e=[]
+if(Array.isArray(t))e=t
+else if("number"==typeof t.length)for(var i=0;i<t.length;i++)e.push(t[i])
+else e.push(t)
+return e}function o(t,e,r){return this instanceof o?("string"==typeof t&&(t=document.querySelectorAll(t)),this.elements=n(t),this.options=i({},this.options),"function"==typeof e?r=e:i(this.options,e),r&&this.on("always",r),this.getImages(),h&&(this.jqDeferred=new h.Deferred),void setTimeout(function(){this.check()}.bind(this))):new o(t,e,r)}function r(t){this.img=t}function s(t,e){this.url=t,this.element=e,this.img=new Image}var h=t.jQuery,a=t.console
+o.prototype=Object.create(e.prototype),o.prototype.options={},o.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)},o.prototype.addElementImages=function(t){"IMG"==t.nodeName&&this.addImage(t),this.options.background===!0&&this.addElementBackgroundImages(t)
+var e=t.nodeType
+if(e&&d[e]){for(var i=t.querySelectorAll("img"),n=0;n<i.length;n++){var o=i[n]
+this.addImage(o)}if("string"==typeof this.options.background){var r=t.querySelectorAll(this.options.background)
+for(n=0;n<r.length;n++){var s=r[n]
+this.addElementBackgroundImages(s)}}}}
+var d={1:!0,9:!0,11:!0}
+return o.prototype.addElementBackgroundImages=function(t){var e=getComputedStyle(t)
+if(e)for(var i=/url\((['"])?(.*?)\1\)/gi,n=i.exec(e.backgroundImage);null!==n;){var o=n&&n[2]
+o&&this.addBackground(o,t),n=i.exec(e.backgroundImage)}},o.prototype.addImage=function(t){var e=new r(t)
+this.images.push(e)},o.prototype.addBackground=function(t,e){var i=new s(t,e)
+this.images.push(i)},o.prototype.check=function(){function t(t,i,n){setTimeout(function(){e.progress(t,i,n)})}var e=this
+return this.progressedCount=0,this.hasAnyBroken=!1,this.images.length?void this.images.forEach(function(e){e.once("progress",t),e.check()}):void this.complete()},o.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount==this.images.length&&this.complete(),this.options.debug&&a&&a.log("progress: "+i,t,e)},o.prototype.complete=function(){var t=this.hasAnyBroken?"fail":"done"
+if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){var e=this.hasAnyBroken?"reject":"resolve"
+this.jqDeferred[e](this)}},r.prototype=Object.create(e.prototype),r.prototype.check=function(){var t=this.getIsImageComplete()
+return t?void this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),void(this.proxyImage.src=this.img.src))},r.prototype.getIsImageComplete=function(){return this.img.complete&&void 0!==this.img.naturalWidth},r.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.img,e])},r.prototype.handleEvent=function(t){var e="on"+t.type
+this[e]&&this[e](t)},r.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},r.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},r.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},s.prototype=Object.create(r.prototype),s.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url
+var t=this.getIsImageComplete()
+t&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},s.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},s.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},o.makeJQueryPlugin=function(e){e=e||t.jQuery,e&&(h=e,h.fn.imagesLoaded=function(t,e){var i=new o(this,t,e)
+return i.jqDeferred.promise(h(this))})},o.makeJQueryPlugin(),o})
diff --git a/www/external/ion-pullup.min.js b/www/external/ion-pullup.min.js
new file mode 100644
index 00000000..047f0837
--- /dev/null
+++ b/www/external/ion-pullup.min.js
@@ -0,0 +1,10 @@
+angular.module("ionic-pullup",[]).constant("ionPullUpFooterState",{COLLAPSED:"COLLAPSED",MINIMIZED:"MINIMIZED",EXPANDED:"EXPANDED"}).constant("ionPullUpFooterBehavior",{HIDE:"HIDE",EXPAND:"EXPAND"}).directive("ionPullUpFooter",["$timeout","$rootScope","$window","$ionicPlatform",function(t,e,n,i){return{restrict:"AE",scope:{onExpand:"&",onCollapse:"&",onMinimize:"&"},controller:["$scope","$element","$attrs","ionPullUpFooterState","ionPullUpFooterBehavior",function(o,a,r,s,l){function u(){c(),a.css({transition:"300ms ease-in-out",padding:0}),P&&E&&a.css("bottom",P.offsetHeight+"px")}function c(){P=document.querySelector(".tabs"),E=document.querySelector(".tabs-bottom"),D=document.querySelector(".bar-header"),H=P?P.offsetHeight:0,x=D?D.offsetHeight:0}function p(){I.height=I.maxHeight>0?I.maxHeight:n.innerHeight-x-v-H,"ios"==e.platformOS&&(I.height-=60),"android"==e.platformOS&&(I.height-=40),a.css({height:I.height+"px"}),I.initialState==s.MINIMIZED?m():f()}function h(){t(function(){p()},300),a.css({transition:"none",padding:0})}function d(){c(),I.height=I.maxHeight>0?I.maxHeight:n.innerHeight-x-v-H,"ios"==e.platformOS&&(I.height-=60),"android"==e.platformOS&&(I.height-=40)}function g(){d(),I.lastPosY=0,a.css({height:I.height+"px","-webkit-transform":"translate3d(0, 0, 0)",transform:"translate3d(0, 0, 0)"}),a.css({transition:"300ms ease-in-out",padding:0}),o.onExpand(),I.state=s.EXPANDED}function f(){I.lastPosY=P&&E?I.height-H:I.height-I.defaultHeight,a.css({"-webkit-transform":"translate3d(0, "+I.lastPosY+"px, 0)",transform:"translate3d(0, "+I.lastPosY+"px, 0)"}),o.onCollapse(),I.state=s.COLLAPSED}function m(){I.lastPosY=I.height,a.css({"-webkit-transform":"translate3d(0, "+I.lastPosY+"px, 0)",transform:"translate3d(0, "+I.lastPosY+"px, 0)"}),o.onMinimize(),I.state=s.MINIMIZED}var P,E,D,H,x,v=0,I={height:0,posY:0,lastPosY:0,state:s.COLLAPSED,defaultHeight:a[0].offsetHeight,maxHeight:parseInt(r.maxHeight,10)||0,initialState:r.initialState?r.initialState.toUpperCase():s.COLLAPSED,defaultBehavior:r.defaultBehavior?r.defaultBehavior.toUpperCase():l.EXPAND}
+this.setHandleHeight=function(t){v=t,p()},this.getHeight=function(){return a[0].offsetHeight},this.getBackground=function(){return n.getComputedStyle(a[0]).background},this.onTap=function(t){t.gesture.srcEvent.preventDefault(),t.gesture.preventDefault(),I.state==s.COLLAPSED?I.defaultBehavior==l.HIDE?m():g():I.state==s.MINIMIZED?I.defaultBehavior==l.HIDE?f():g():I.initialState==s.MINIMIZED?m():f(),e.$broadcast("ionPullUp:tap",I.state)},this.onDrag=function(t){switch(t.gesture.srcEvent.preventDefault(),t.gesture.preventDefault(),t.type){case"dragstart":a.css("transition","none")
+break
+case"drag":if(I.posY=Math.round(t.gesture.deltaY)+I.lastPosY,I.posY<0||I.posY>I.height)return
+a.css({"-webkit-transform":"translate3d(0, "+I.posY+"px, 0)",transform:"translate3d(0, "+I.posY+"px, 0)"})
+break
+case"dragend":a.css({transition:"300ms ease-in-out"}),I.lastPosY=I.posY}},u(),i.ready(function(){n.addEventListener("orientationchange",h),i.on("resume",h)})}],compile:function(t,e){e.defaultHeight&&t.css("height",parseInt(e.defaultHeight,10)+"px"),t.addClass("bar bar-footer")}}}]).directive("ionPullUpContent",[function(){return{restrict:"AE",require:"^ionPullUpFooter",link:function(t,e,n,i){var o=i.getHeight()
+e.css({display:"block","margin-top":o+"px",width:"100%"}),n.scroll&&"TRUE"==n.scroll.toUpperCase()&&e.css({"overflow-y":"scroll","overflow-x":"hidden"})}}}]).directive("ionPullUpBar",[function(){return{restrict:"AE",require:"^ionPullUpFooter",link:function(t,e,n,i){var o=i.getHeight()
+e.css({display:"flex",height:o+"px",position:"absolute",right:"0",left:"0"})}}}]).directive("ionPullUpTrigger",["$ionicGesture",function(t){return{restrict:"AE",require:"^ionPullUpFooter",link:function(e,n,i,o){t.on("tap",o.onTap,n),t.on("drag dragstart dragend",o.onDrag,n)}}}]).directive("ionPullUpHandle",["$ionicGesture","$ionicPlatform","$timeout","$window",function(t,e,n,i){return{restrict:"AE",require:"^ionPullUpFooter",link:function(o,a,r,s){function l(){n(function(){a.css("left",(i.innerWidth-c)/2+"px")},300)}var u=parseInt(r.height,10)||25,c=parseInt(r.width,10)||100,p=s.getBackground(),h=r.toggle
+s.setHandleHeight(u),a.css({display:"block",background:p,position:"absolute",top:1-u+"px",left:(i.innerWidth-c)/2+"px",height:u+"px",width:c+"px","text-align":"center"}),t.on("tap",s.onTap,a),t.on("drag dragstart dragend",s.onDrag,a),o.$on("ionPullUp:tap",function(){a.find("i").toggleClass(h)}),e.ready(function(){i.addEventListener("orientationchange",l),e.on("resume",l)})}}}])
diff --git a/www/external/ionRadio.min.js b/www/external/ionRadio.min.js
new file mode 100644
index 00000000..d652fdda
--- /dev/null
+++ b/www/external/ionRadio.min.js
@@ -0,0 +1,12 @@
+/**
+ * ionRadioFix - fixes a bug in iOS 9 UIWebView that breaks the tilde selector in CSS. To
+ * use this fix, include it after your Ionic bundle JS.
+ *
+ * Note: due to Angular directive override limitations, you'll need to change any reference
+ * to <ion-radio> to <ion-radio-fix> to apply this patched radio button.
+ *
+ * Also, make sure to add the new CSS from the second part of this gist.
+ */
+angular.module("ionic").directive("ionRadioFix",function(){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<label class="item item-radio"><input type="radio" name="radio-group"><div class="radio-content"><div class="item-content disable-pointer-events" ng-transclude></div><i class="radio-icon disable-pointer-events icon ion-checkmark"></i></div></label>',compile:function(e,n){if(n.icon){var i=e.find("i")
+i.removeClass("ion-checkmark").addClass(n.icon)}var a=e.find("input")
+return angular.forEach({name:n.name,value:n.value,disabled:n.disabled,"ng-value":n.ngValue,"ng-model":n.ngModel,"ng-disabled":n.ngDisabled,"ng-change":n.ngChange,"ng-required":n.ngRequired,required:n.required},function(e,n){angular.isDefined(e)&&a.attr(n,e)}),function(e,n,i){e.getValue=function(){return e.ngValue||i.value}}}}})
diff --git a/www/external/ionic.content.banner.min.js b/www/external/ionic.content.banner.min.js
new file mode 100644
index 00000000..62b317ce
--- /dev/null
+++ b/www/external/ionic.content.banner.min.js
@@ -0,0 +1,12 @@
+angular.module("jett.ionic.content.banner",["ionic"]),function(n){"use strict"
+n.module("jett.ionic.content.banner").directive("ionContentBanner",["$interval",function(n){return{restrict:"E",scope:!0,link:function(e,t){var o
+e.currentIndex=0,e.text.length>1&&(o=n(function(){e.currentIndex=e.currentIndex<e.text.length-1?e.currentIndex+1:0},e.interval)),e.$on("$destroy",function(){t.remove(),o&&n.cancel(o)})},template:'<div class="content-banner-text-wrapper"><div ng-repeat="item in text track by $index" ng-class="{active: $index === currentIndex}" class="content-banner-text" ng-bind="item"></div></div><button class="content-banner-close button button-icon icon {{::icon}}" ng-click="close()"></button>'}}])}(angular),function(n,e){"use strict"
+n.module("jett.ionic.content.banner").factory("$ionicContentBanner",["$document","$rootScope","$compile","$timeout","$ionicPlatform",function(t,o,r,i,c){function a(n){for(;null!==n&&"BODY"!==n.nodeName;){var e=n.getAttribute("nav-view")
+if(null!==e&&"cached"===e)return!1
+n=n.parentNode}return!0}function u(n){var e=n.querySelector('ion-modal-view[class*="ng-enter-active"]')
+if(null!=e&&e.getAttribute("class").indexOf("ng-leave")==-1)return e
+var t=n.querySelectorAll('ion-view[nav-view="active"]')
+return 1===t.length?t[0]:Array.prototype.slice.call(t).filter(function(n){return a(n)})[0]}function l(a){var l=o.$new(!0)
+n.extend(l,{icon:"ion-ios-close-empty",transition:"vertical",interval:7e3,type:"info",$deregisterBackButton:n.noop,closeOnStateChange:!0,autoClose:null},a)
+var s="content-banner "+l.type+" content-banner-transition-"+l.transition,d=l.element=r('<ion-content-banner class="'+s+'"></ion-content-banner>')(l),v=t[0].body,f=l.closeOnStateChange?o.$on("$stateChangeSuccess",function(){l.close()}):n.noop
+return l.$deregisterBackButton=c.registerBackButtonAction(function(){i(l.close)},300),l.close=function(){l.removed||(l.removed=!0,e.requestAnimationFrame(function(){d.removeClass("content-banner-in"),i(function(){l.$destroy(),d.remove(),v=f=null},400)}),l.$deregisterBackButton(),f())},l.show=function(){l.removed||(void 0!==u(v)&&u(v).querySelector(".scroll-content").appendChild(d[0]),e.requestAnimationFrame(function(){i(function(){d.addClass("content-banner-in"),l.autoClose&&i(function(){l.close()},l.autoClose,!1)},20,!1)}))},i(function(){l.show()},10,!1),l.close.$scope=l,l.close}return{show:l}}])}(angular,ionic)
diff --git a/www/external/ionic.scroll.sista.min.js b/www/external/ionic.scroll.sista.min.js
new file mode 100644
index 00000000..a49a1a3d
--- /dev/null
+++ b/www/external/ionic.scroll.sista.min.js
@@ -0,0 +1,28 @@
+/* global angular,ionic */
+!function(e,t){"use strict"
+e.module("jett.ionic.scroll.sista",["ionic"]).directive("scrollSista",["$document","$timeout","$rootScope","$ionicScrollDelegate","$ionicPlatform",function(a,n,r,o,i){function c(e,t,a,n){var r
+for(n=n||10;e.parentNode&&n--;){if(r=e.parentNode.getAttribute(t),r&&r===a)return e.parentNode
+e=e.parentNode}return null}var l=400,s=2*l,u=!t.Platform.isAndroid()
+return{restrict:"A",link:function(r,l,f){function d(e,a,r){r&&!e.style[t.CSS.TRANSITION_DURATION]&&(e.style[t.CSS.TRANSITION_DURATION]=r,n(function(){e.style[t.CSS.TRANSITION_DURATION]=""},s,!1)),e.style[t.CSS.TRANSFORM]="translate3d(0, "+-a+"px, 0)"}function b(){v=0,N=0,$=0}function h(){var e
+if(y=q.querySelector('[nav-bar="cached"] .bar-header'),g=q.querySelector('[nav-bar="active"] .bar-header'))switch(T=g.offsetHeight,i.ready(function(){i.is("ios")&&(V=!0,T-=20)}),A=T,I=q.querySelectorAll(".tabs"),I=I[I.length-1],I&&(k=I.offsetHeight,I.parentNode.classList.contains("tabs-top")?(F=!0,A+=k):I.parentNode.classList.contains("tabs-bottom")&&(L=!0)),e=c(l[0],"nav-view","active"),M=e&&e.querySelector(".bar-subheader"),M&&(R=M.offsetHeight,A+=R),x=2*A,O=w=C=x,k=k||0,R=R||0,f.scrollSista){case"header":C=T,w=F?T:0
+break
+case"header-tabs":U=F?k:0,C=F?T+k:T
+break
+case"tabs-subheader":O=0,U=F?A-T:R,_=F?R:0
+break
+case"tabs":O=0,C=F?k:0
+break
+case"subheader":O=0,w=0
+break
+case"header-subheader":w=F?T:0
+break
+case"subheader-header":U=R,_=F?R:0,w=F?T:0
+break
+default:U=F?A-T:R,_=F?R:0}}function S(a,n){var r=Math.max(0,1-a/T)
+g&&(d(g,a,n),e.forEach(g.children,function(e){e.style.opacity=r,u&&(e.style[t.CSS.TRANSFORM]="scale("+r+","+r+")")})),y&&d(y,a,n)}function p(e,t){var a,n,r=l[0].style,o=e>U?e-U:0
+M&&(n=e>P?e-P:0,d(M,Math.min(C,n),t)),I&&(a=Math.min(w,e>_?e-_:0),L&&(a=-a,r.bottom=Math.max(0,k-e)+"px"),d(I,a,t)),S(Math.min(O,o),t)
+var i=Math.max(0,A-e)
+V&&(i+=20),r.top=i+"px"}function m(e,a){t.requestAnimationFrame(function(){p(e,a)})}var v,N,$,y,g,T,A,M,R,I,k,x,O,w,C,H=!0,q=a[0].body,D=f.delegateHandle?o.$getByHandle(f.delegateHandle):o,E=D.getScrollView(),V=!1,F=!1,L=!1,U=0,_=0,P=0
+r.$on("scroll.refreshComplete",function(){b()}),r.$parent.$on("$ionicView.beforeLeave",function(){H=!0,p(0),g=null,y=null}),r.$parent.$on("$ionicView.beforeEnter",function(){E&&E.scrollTo(0,0)}),r.$parent.$on("$ionicView.afterEnter",function(){b(),n(function(){h(),H=!1},20,!1)}),l.bind("scroll",function(e){if(!H){e=e.originalEvent||e
+var t=0,a=e.detail?e.detail.scrollTop:e.target.scrollTop
+v=a>=0?Math.min(x,Math.max(0,v+a-$)):0,V&&v>T&&(v=T),E.getScrollMax().top-a<=A,$=a,N!==v&&(N=v,m(v,t))}})}}}])}(angular,ionic)
diff --git a/www/external/ng-websocket.min.js b/www/external/ng-websocket.min.js
new file mode 100644
index 00000000..a988667b
--- /dev/null
+++ b/www/external/ng-websocket.min.js
@@ -0,0 +1,31 @@
+"use strict"
+!function(){function e(){var e=this
+e.$$config={lazy:!1,reconnect:!0,reconnectInterval:2e3,mock:!1,enqueue:!1,protocols:null},e.$setup=function(n){return n=n||{},e.$$config=angular.extend({},e.$$config,n),e},e.$get=["$http",function(t){return new n(e.$$config,t)}]}function n(e,n){var o=this
+o.$$websocketList={},o.$$config=e||{},o.$get=function(e){return o.$$websocketList[e]},o.$new=function(e){e=e||{},"string"==typeof e&&(e={url:e},arguments.length>1&&("string"==typeof arguments[1]&&arguments[1].length>0?e.protocols=[arguments[1]]:"object"==typeof arguments[1]&&arguments[1].length>0&&(e.protocols=arguments[1])))
+var r=o.$get(e.url)
+if("undefined"==typeof r){var $=angular.extend({},o.$$config,e)
+r=new t($,n),o.$$websocketList[$.url]=r}return r}}function t(e,n){var t=this
+if("undefined"==typeof e||"object"==typeof e&&"undefined"==typeof e.url)throw new Error("An url must be specified for WebSocket")
+return t.$$eventMap={},t.$$ws=void 0,t.$$reconnectTask=void 0,t.$$reconnectCopy=!0,t.$$queue=[],t.$$config={url:void 0,lazy:!1,reconnect:!0,reconnectInterval:2e3,enqueue:!1,mock:!1,protocols:null},t.$$fireEvent=function(){var e=[]
+Array.prototype.push.apply(e,arguments)
+var n=e.shift(),o=t.$$eventMap[n]
+if("undefined"!=typeof o)for(var r=0;r<o.length;r++)"function"==typeof o[r]&&o[r].apply(t,e)},t.$$init=function(e){return e.mock?t.$$ws=new o(e.mock,n):e.protocols?t.$$ws=new WebSocket(e.url,e.protocols):t.$$ws=new WebSocket(e.url),t.$$ws.onmessage=function(e){try{var n=JSON.parse(e.data)
+t.$$fireEvent(n.event,n.data),t.$$fireEvent("$message",n)}catch(n){t.$$fireEvent("$message",e.data)}},t.$$ws.onerror=function(e){t.$$fireEvent("$error",e)},t.$$ws.onopen=function(){if(t.$$reconnectTask&&(clearInterval(t.$$reconnectTask),delete t.$$reconnectTask),t.$$config.enqueue&&t.$$queue.length>0)for(;t.$$queue.length>0&&t.$ready();)t.$$send(t.$$queue.shift())
+t.$$fireEvent("$open")},t.$$ws.onclose=function(){t.$$config.reconnect&&!t.$$reconnectTask&&(t.$$reconnectTask=setInterval(function(){t.$status()===t.$CLOSED&&t.$open()},t.$$config.reconnectInterval)),t.$$fireEvent("$close")},t},t.$CONNECTING=0,t.$OPEN=1,t.$CLOSING=2,t.$CLOSED=3,t.$on=function(){var e=[]
+Array.prototype.push.apply(e,arguments)
+var n=e.shift()
+if("string"!=typeof n||0===e.length)throw new Error("$on accept two parameters at least: a String and a Function or an array of Functions")
+t.$$eventMap[n]=t.$$eventMap[n]||[]
+for(var o=0;o<e.length;o++)t.$$eventMap[n].push(e[o])
+return t},t.$un=function(e){if("string"!=typeof e)throw new Error("$un needs a String representing an event.")
+return"undefined"!=typeof t.$$eventMap[e]&&delete t.$$eventMap[e],t},t.$$send=function(e){t.$ready()?t.$$ws.send(JSON.stringify(e)):t.$$config.enqueue&&t.$$queue.push(e)},t.$emit=function(e,n){if("string"!=typeof e)throw new Error("$emit needs two parameter: a String and a Object or a String")
+var o={event:e,data:n}
+return t.$$send(o),t},t.$open=function(){return t.$$config.reconnect=t.$$reconnectCopy,t.$status()!==t.$OPEN&&t.$$init(t.$$config),t},t.$close=function(){return t.$status()!==t.$CLOSED&&t.$$ws.close(),t.$$reconnectTask&&(clearInterval(t.$$reconnectTask),delete t.$$reconnectTask),t.$$config.reconnect=!1,t},t.$status=function(){return"undefined"==typeof t.$$ws?t.$CLOSED:t.$$ws.readyState},t.$ready=function(){return t.$status()===t.$OPEN},t.$mockup=function(){return t.$$config.mock},t.$$config=angular.extend({},t.$$config,e),t.$$reconnectCopy=t.$$config.reconnect,t.$$config.lazy||t.$$init(t.$$config),t}function o(e,n){e=e||{}
+var t=this,o=e.openTimeout||500,r=e.closeTimeout||1e3,$=e.messageInterval||2e3,c=e.fixtures||{},a=[]
+t.CONNECTING=0,t.OPEN=1,t.CLOSING=2,t.CLOSED=3,t.readyState=t.CONNECTING,t.send=function(e){if(t.readyState===t.OPEN)return a.push(e),t
+throw new Error("WebSocket is already in CLOSING or CLOSED state.")},t.close=function(){return t.readyState===t.OPEN&&(t.readyState=t.CLOSING,setTimeout(function(){t.readyState=t.CLOSED,t.onclose()},r)),t},t.onmessage=function(){},t.onerror=function(){},t.onopen=function(){},t.onclose=function(){},setInterval(function(){if(a.length>0){var e=a.shift(),n=JSON.parse(e)
+switch(n.event){case"$close":t.close()
+break
+default:"undefined"!=typeof c[n.event]&&(n.data=c[n.event].data||n.data,n.event=c[n.event].event||n.event),e=JSON.stringify(n),t.onmessage({data:e})}}},$)
+var i=function(e){e=e||{},e=e instanceof Error?{}:e,c=e,setTimeout(function(){t.readyState=t.OPEN,t.onopen()},o)}
+return"string"==typeof c?n.get(c).success(i).error(i):i(c),t}angular.module("ngWebsocket",[]).provider("$websocket",e)}()
diff --git a/www/external/origjs/NeuQuant.js b/www/external/origjs/NeuQuant.js
new file mode 100644
index 00000000..f0c124ba
--- /dev/null
+++ b/www/external/origjs/NeuQuant.js
@@ -0,0 +1,389 @@
+NeuQuant = function () {
+ function NeuQuant() {
+ var netsize = 256;
+ var prime1 = 499;
+ var prime2 = 491;
+ var prime3 = 487;
+ var prime4 = 503;
+ var minpicturebytes = 3 * prime4;
+ var maxnetpos = netsize - 1;
+ var netbiasshift = 4;
+ var ncycles = 100;
+ var intbiasshift = 16;
+ var intbias = 1 << intbiasshift;
+ var gammashift = 10;
+ var gamma = 1 << gammashift;
+ var betashift = 10;
+ var beta = intbias >> betashift;
+ var betagamma = intbias << gammashift - betashift;
+ var initrad = netsize >> 3;
+ var radiusbiasshift = 6;
+ var radiusbias = 1 << radiusbiasshift;
+ var initradius = initrad * radiusbias;
+ var radiusdec = 30;
+ var alphabiasshift = 10;
+ var initalpha = 1 << alphabiasshift;
+ var alphadec;
+ var radbiasshift = 8;
+ var radbias = 1 << radbiasshift;
+ var alpharadbshift = alphabiasshift + radbiasshift;
+ var alpharadbias = 1 << alpharadbshift;
+ var thepicture;
+ var lengthcount;
+ var samplefac;
+ var network;
+ var netindex = [];
+ var bias = [];
+ var freq = [];
+ var radpower = [];
+ function NeuQuantConstructor(thepic, len, sample) {
+ var i;
+ var p;
+ thepicture = thepic;
+ lengthcount = len;
+ samplefac = sample;
+ network = new Array(netsize);
+ for (i = 0; i < netsize; i++) {
+ network[i] = new Array(4);
+ p = network[i];
+ p[0] = p[1] = p[2] = (i << netbiasshift + 8) / netsize | 0;
+ freq[i] = intbias / netsize | 0;
+ bias[i] = 0;
+ }
+ }
+ function colorMap() {
+ var map = [];
+ var index = new Array(netsize);
+ for (var i = 0; i < netsize; i++)
+ index[network[i][3]] = i;
+ var k = 0;
+ for (var l = 0; l < netsize; l++) {
+ var j = index[l];
+ map[k++] = network[j][0];
+ map[k++] = network[j][1];
+ map[k++] = network[j][2];
+ }
+ return map;
+ }
+ function inxbuild() {
+ var i;
+ var j;
+ var smallpos;
+ var smallval;
+ var p;
+ var q;
+ var previouscol;
+ var startpos;
+ previouscol = 0;
+ startpos = 0;
+ for (i = 0; i < netsize; i++) {
+ p = network[i];
+ smallpos = i;
+ smallval = p[1];
+ for (j = i + 1; j < netsize; j++) {
+ q = network[j];
+ if (q[1] < smallval) {
+ smallpos = j;
+ smallval = q[1];
+ }
+ }
+ q = network[smallpos];
+ if (i != smallpos) {
+ j = q[0];
+ q[0] = p[0];
+ p[0] = j;
+ j = q[1];
+ q[1] = p[1];
+ p[1] = j;
+ j = q[2];
+ q[2] = p[2];
+ p[2] = j;
+ j = q[3];
+ q[3] = p[3];
+ p[3] = j;
+ }
+ if (smallval != previouscol) {
+ netindex[previouscol] = startpos + i >> 1;
+ for (j = previouscol + 1; j < smallval; j++) {
+ netindex[j] = i;
+ }
+ previouscol = smallval;
+ startpos = i;
+ }
+ }
+ netindex[previouscol] = startpos + maxnetpos >> 1;
+ for (j = previouscol + 1; j < 256; j++) {
+ netindex[j] = maxnetpos;
+ }
+ }
+ function learn() {
+ var i;
+ var j;
+ var b;
+ var g;
+ var r;
+ var radius;
+ var rad;
+ var alpha;
+ var step;
+ var delta;
+ var samplepixels;
+ var p;
+ var pix;
+ var lim;
+ if (lengthcount < minpicturebytes) {
+ samplefac = 1;
+ }
+ alphadec = 30 + (samplefac - 1) / 3;
+ p = thepicture;
+ pix = 0;
+ lim = lengthcount;
+ samplepixels = lengthcount / (3 * samplefac);
+ delta = samplepixels / ncycles | 0;
+ alpha = initalpha;
+ radius = initradius;
+ rad = radius >> radiusbiasshift;
+ if (rad <= 1) {
+ rad = 0;
+ }
+ for (i = 0; i < rad; i++) {
+ radpower[i] = alpha * ((rad * rad - i * i) * radbias / (rad * rad));
+ }
+ if (lengthcount < minpicturebytes) {
+ step = 3;
+ } else if (lengthcount % prime1 !== 0) {
+ step = 3 * prime1;
+ } else {
+ if (lengthcount % prime2 !== 0) {
+ step = 3 * prime2;
+ } else {
+ if (lengthcount % prime3 !== 0) {
+ step = 3 * prime3;
+ } else {
+ step = 3 * prime4;
+ }
+ }
+ }
+ i = 0;
+ while (i < samplepixels) {
+ b = (p[pix + 0] & 255) << netbiasshift;
+ g = (p[pix + 1] & 255) << netbiasshift;
+ r = (p[pix + 2] & 255) << netbiasshift;
+ j = contest(b, g, r);
+ altersingle(alpha, j, b, g, r);
+ if (rad !== 0) {
+ alterneigh(rad, j, b, g, r);
+ }
+ pix += step;
+ if (pix >= lim) {
+ pix -= lengthcount;
+ }
+ i++;
+ if (delta === 0) {
+ delta = 1;
+ }
+ if (i % delta === 0) {
+ alpha -= alpha / alphadec;
+ radius -= radius / radiusdec;
+ rad = radius >> radiusbiasshift;
+ if (rad <= 1) {
+ rad = 0;
+ }
+ for (j = 0; j < rad; j++) {
+ radpower[j] = alpha * ((rad * rad - j * j) * radbias / (rad * rad));
+ }
+ }
+ }
+ }
+ function map(b, g, r) {
+ var i;
+ var j;
+ var dist;
+ var a;
+ var bestd;
+ var p;
+ var best;
+ bestd = 1000;
+ best = -1;
+ i = netindex[g];
+ j = i - 1;
+ while (i < netsize || j >= 0) {
+ if (i < netsize) {
+ p = network[i];
+ dist = p[1] - g;
+ if (dist >= bestd) {
+ i = netsize;
+ } else {
+ i++;
+ if (dist < 0) {
+ dist = -dist;
+ }
+ a = p[0] - b;
+ if (a < 0) {
+ a = -a;
+ }
+ dist += a;
+ if (dist < bestd) {
+ a = p[2] - r;
+ if (a < 0) {
+ a = -a;
+ }
+ dist += a;
+ if (dist < bestd) {
+ bestd = dist;
+ best = p[3];
+ }
+ }
+ }
+ }
+ if (j >= 0) {
+ p = network[j];
+ dist = g - p[1];
+ if (dist >= bestd) {
+ j = -1;
+ } else {
+ j--;
+ if (dist < 0) {
+ dist = -dist;
+ }
+ a = p[0] - b;
+ if (a < 0) {
+ a = -a;
+ }
+ dist += a;
+ if (dist < bestd) {
+ a = p[2] - r;
+ if (a < 0) {
+ a = -a;
+ }
+ dist += a;
+ if (dist < bestd) {
+ bestd = dist;
+ best = p[3];
+ }
+ }
+ }
+ }
+ }
+ return best;
+ }
+ function process() {
+ learn();
+ unbiasnet();
+ inxbuild();
+ return colorMap();
+ }
+ function unbiasnet() {
+ var i;
+ var j;
+ for (i = 0; i < netsize; i++) {
+ network[i][0] >>= netbiasshift;
+ network[i][1] >>= netbiasshift;
+ network[i][2] >>= netbiasshift;
+ network[i][3] = i;
+ }
+ }
+ function alterneigh(rad, i, b, g, r) {
+ var j;
+ var k;
+ var lo;
+ var hi;
+ var a;
+ var m;
+ var p;
+ lo = i - rad;
+ if (lo < -1) {
+ lo = -1;
+ }
+ hi = i + rad;
+ if (hi > netsize) {
+ hi = netsize;
+ }
+ j = i + 1;
+ k = i - 1;
+ m = 1;
+ while (j < hi || k > lo) {
+ a = radpower[m++];
+ if (j < hi) {
+ p = network[j++];
+ try {
+ p[0] -= a * (p[0] - b) / alpharadbias | 0;
+ p[1] -= a * (p[1] - g) / alpharadbias | 0;
+ p[2] -= a * (p[2] - r) / alpharadbias | 0;
+ } catch (e) {
+ }
+ }
+ if (k > lo) {
+ p = network[k--];
+ try {
+ p[0] -= a * (p[0] - b) / alpharadbias | 0;
+ p[1] -= a * (p[1] - g) / alpharadbias | 0;
+ p[2] -= a * (p[2] - r) / alpharadbias | 0;
+ } catch (e) {
+ }
+ }
+ }
+ }
+ function altersingle(alpha, i, b, g, r) {
+ var n = network[i];
+ var alphaMult = alpha / initalpha;
+ n[0] -= alphaMult * (n[0] - b) | 0;
+ n[1] -= alphaMult * (n[1] - g) | 0;
+ n[2] -= alphaMult * (n[2] - r) | 0;
+ }
+ function contest(b, g, r) {
+ var i;
+ var dist;
+ var a;
+ var biasdist;
+ var betafreq;
+ var bestpos;
+ var bestbiaspos;
+ var bestd;
+ var bestbiasd;
+ var n;
+ bestd = ~(1 << 31);
+ bestbiasd = bestd;
+ bestpos = -1;
+ bestbiaspos = bestpos;
+ for (i = 0; i < netsize; i++) {
+ n = network[i];
+ dist = n[0] - b;
+ if (dist < 0) {
+ dist = -dist;
+ }
+ a = n[1] - g;
+ if (a < 0) {
+ a = -a;
+ }
+ dist += a;
+ a = n[2] - r;
+ if (a < 0) {
+ a = -a;
+ }
+ dist += a;
+ if (dist < bestd) {
+ bestd = dist;
+ bestpos = i;
+ }
+ biasdist = dist - (bias[i] >> intbiasshift - netbiasshift);
+ if (biasdist < bestbiasd) {
+ bestbiasd = biasdist;
+ bestbiaspos = i;
+ }
+ betafreq = freq[i] >> betashift;
+ freq[i] -= betafreq;
+ bias[i] += betafreq << gammashift;
+ }
+ freq[bestpos] += beta;
+ bias[bestpos] -= betagamma;
+ return bestbiaspos;
+ }
+ NeuQuantConstructor.apply(this, arguments);
+ var exports = {};
+ exports.map = map;
+ exports.process = process;
+ return exports;
+ }
+ return NeuQuant;
+}(); \ No newline at end of file
diff --git a/www/external/origjs/README.TXT b/www/external/origjs/README.TXT
new file mode 100644
index 00000000..19a2b36d
--- /dev/null
+++ b/www/external/origjs/README.TXT
@@ -0,0 +1,3 @@
+These are original JS files.
+I minified then in externals/ using npm minify
+~pp
diff --git a/www/external/angular-carousel.js b/www/external/origjs/angular-carousel.js
index 21cc6729..48c94258 100644
--- a/www/external/angular-carousel.js
+++ b/www/external/origjs/angular-carousel.js
@@ -1,23 +1,21 @@
-/* jshint ignore:start */
-/**
-
- * Angular Carousel - Mobile friendly touch carousel for AngularJS
- * @version v0.3.12 - 2015-06-11
- * @link http://revolunet.github.com/angular-carousel
- * @author Julien Bouquillon <julien@revolunet.com>
- * @license MIT License, http://www.opensource.org/licenses/MIT
- */
-/*global angular */
-/*
-Angular touch carousel with CSS GPU accel and slide buffering
-http://github.com/revolunet/angular-carousel
+//Angular Carousel - Mobile friendly touch carousel for AngularJS
+//@version v0.3.12 - 2015-06-11
+//@link http://revolunet.github.com/angular-carousel
+//@author Julien Bouquillon <julien@revolunet.com>
+//@license MIT License, http://www.opensource.org/licenses/MIT
+
+
+
+//Angular touch carousel with CSS GPU accel and slide buffering
+//http://github.com/revolunet/angular-carousel
-*/
// Modified by PP for mobile friendly touch, start without auto slide but enabled it if tapped
// and logic to wait for an image to load before it slides to the next one
+/* jshint ignore:start */
+/*global angular */
angular.module('angular-carousel', [
'ngTouch',
'angular-carousel.shifty'
diff --git a/www/external/angular-circular-navigation.js b/www/external/origjs/angular-circular-navigation.js
index 17488768..17488768 100644
--- a/www/external/angular-circular-navigation.js
+++ b/www/external/origjs/angular-circular-navigation.js
diff --git a/www/external/origjs/angular-ios9-uiwebview.patch.js b/www/external/origjs/angular-ios9-uiwebview.patch.js
new file mode 100644
index 00000000..c52cad82
--- /dev/null
+++ b/www/external/origjs/angular-ios9-uiwebview.patch.js
@@ -0,0 +1,73 @@
+/**
+ * ================== angular-ios9-uiwebview.patch.js v1.1.0 ==================
+ *
+ * This patch works around iOS9 UIWebView regression that causes infinite digest
+ * errors in Angular.
+ *
+ * The patch can be applied to Angular 1.2.0 – 1.4.5. Newer versions of Angular
+ * have the workaround baked in.
+ *
+ * To apply this patch load/bundle this file with your application and add a
+ * dependency on the "ngIOS9Patch" module to your main app module.
+ *
+ * For example:
+ *
+ * ```
+ * angular.module('myApp', ['ngRoute'])`
+ * ```
+ *
+ * becomes
+ *
+ * ```
+ * angular.module('myApp', ['ngRoute', 'ngIOS9UIWebViewPatch'])
+ * ```
+ *
+ *
+ * More info:
+ * - https://openradar.appspot.com/22186109
+ * - https://github.com/angular/angular.js/issues/12241
+ * - https://github.com/driftyco/ionic/issues/4082
+ *
+ *
+ * @license AngularJS
+ * (c) 2010-2015 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+
+angular.module('ngIOS9UIWebViewPatch', ['ng']).config(function($provide) {
+ $provide.decorator('$browser', ['$delegate', '$window', function($delegate, $window) {
+
+ if (isIOS9UIWebView($window.navigator.userAgent)) {
+ return applyIOS9Shim($delegate);
+ }
+
+ return $delegate;
+
+ function isIOS9UIWebView(userAgent) {
+ return /(iPhone|iPad|iPod).* OS 9_\d/.test(userAgent) && !/Version\/9\./.test(userAgent);
+ }
+
+ function applyIOS9Shim(browser) {
+ var pendingLocationUrl = null;
+ var originalUrlFn= browser.url;
+
+ browser.url = function() {
+ if (arguments.length) {
+ pendingLocationUrl = arguments[0];
+ return originalUrlFn.apply(browser, arguments);
+ }
+
+ return pendingLocationUrl || originalUrlFn.apply(browser, arguments);
+ };
+
+ window.addEventListener('popstate', clearPendingLocationUrl, false);
+ window.addEventListener('hashchange', clearPendingLocationUrl, false);
+
+ function clearPendingLocationUrl() {
+ pendingLocationUrl = null;
+ }
+
+ return browser;
+ }
+ }]);
+});
diff --git a/www/external/canvas-toBlob.js b/www/external/origjs/canvas-toBlob.js
index 6d895a78..6d895a78 100644
--- a/www/external/canvas-toBlob.js
+++ b/www/external/origjs/canvas-toBlob.js
diff --git a/www/external/draggabilly.pkgd.js b/www/external/origjs/draggabilly.pkgd.js
index bef3db35..bef3db35 100644
--- a/www/external/draggabilly.pkgd.js
+++ b/www/external/origjs/draggabilly.pkgd.js
diff --git a/www/external/origjs/gifwriter.js b/www/external/origjs/gifwriter.js
new file mode 100644
index 00000000..67ae264e
--- /dev/null
+++ b/www/external/origjs/gifwriter.js
@@ -0,0 +1,406 @@
+// (c) Dean McNamee <dean@gmail.com>, 2013.
+// //
+// // https://github.com/deanm/omggif
+// //
+// // 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.
+// //
+// // omggif is a JavaScript implementation of a GIF 89a encoder and decoder,
+// // including animation and compression. It does not rely on any specific
+// // underlying system, so should run in the browser, Node, or Plask.
+'use strict';
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function check_palette_and_num_colors(palette) {
+ var num_colors = palette.length;
+
+ if (num_colors < 2 || num_colors > 256 || num_colors & num_colors - 1) {
+ throw new Error('Invalid code/color length, must be power of 2 and 2 .. 256.');
+ }
+
+ return num_colors;
+}
+
+var GifWriter = function () {
+ function GifWriter(rs, width, height) {
+ var gopts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
+
+ _classCallCheck(this, GifWriter);
+
+ var loop = gopts.loop,
+ palette = gopts.palette;
+
+ var p = 0;
+ var buf = [];
+ var global_palette = palette;
+
+ if (width <= 0 || height <= 0 || width > 65535 || height > 65535) {
+ throw new Error('Width/Height invalid.');
+ }
+
+ // - Header.
+ buf[p++] = 0x47;buf[p++] = 0x49;buf[p++] = 0x46; // GIF
+ buf[p++] = 0x38;buf[p++] = 0x39;buf[p++] = 0x61; // 89a
+
+ // Handling of Global Color Table (palette) and background index.
+ var gp_num_colors_pow2 = 0;
+ var background = 0;
+ if (global_palette) {
+ var gp_num_colors = check_palette_and_num_colors(global_palette);
+ while (gp_num_colors >>= 1) {
+ ++gp_num_colors_pow2;
+ }gp_num_colors = 1 << gp_num_colors_pow2;
+ gp_num_colors_pow2--;
+ if (gopts.background !== undefined) {
+ background = gopts.background;
+ if (background >= gp_num_colors) {
+ throw new Error('Background index out of range.');
+ }
+ // The GIF spec states that a background index of 0 should be ignored, so
+ // this is probably a mistake and you really want to set it to another
+ // slot in the palette. But actually in the end most browsers, etc end
+ // up ignoring this almost completely (including for dispose background).
+ if (background === 0) throw new Error('Background index explicitly passed as 0.');
+ }
+ }
+
+ // - Logical Screen Descriptor.
+ // NOTE(deanm): w/h apparently ignored by implementations, but set anyway.
+ buf[p++] = width & 0xff;
+ buf[p++] = width >> 8 & 0xff;
+ buf[p++] = height & 0xff;
+ buf[p++] = height >> 8 & 0xff;
+
+ // NOTE: Indicates 0-bpp original color resolution (unused?).
+ buf[p++] = (global_palette ? 0x80 : 0) | // Global Color Table Flag.
+ gp_num_colors_pow2; // NOTE: No sort flag (unused?).
+ buf[p++] = background; // Background Color Index.
+ buf[p++] = 0; // Pixel aspect ratio (unused?).
+
+ // - Global Color Table
+ if (global_palette) {
+ for (var _iterator = global_palette, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
+ var _ref;
+
+ if (_isArray) {
+ if (_i >= _iterator.length) break;
+ _ref = _iterator[_i++];
+ } else {
+ _i = _iterator.next();
+ if (_i.done) break;
+ _ref = _i.value;
+ }
+
+ var rgb = _ref;
+
+ buf[p++] = rgb >> 16 & 0xff;
+ buf[p++] = rgb >> 8 & 0xff;
+ buf[p++] = rgb & 0xff;
+ }
+ }
+
+ if (Number.isInteger(loop)) {
+ // Netscape block for looping.
+ if (loop < 0 || loop > 65535) throw "Loop count invalid.";
+ // Extension code, label, and length.
+ buf[p++] = 0x21;buf[p++] = 0xff;buf[p++] = 0x0b;
+ // NETSCAPE2.0
+ buf[p++] = 0x4e;buf[p++] = 0x45;buf[p++] = 0x54;buf[p++] = 0x53;
+ buf[p++] = 0x43;buf[p++] = 0x41;buf[p++] = 0x50;buf[p++] = 0x45;
+ buf[p++] = 0x32;buf[p++] = 0x2e;buf[p++] = 0x30;
+ // Sub-block
+ buf[p++] = 0x03;buf[p++] = 0x01;
+ buf[p++] = loop & 0xff;buf[p++] = loop >> 8 & 0xff;
+ buf[p++] = 0x00; // Terminator.
+ }
+
+ var self = this;
+ var reader = rs.getReader();
+
+ return new ReadableStream({
+ start: function start(controller) {
+ controller.enqueue(new Uint8Array(buf));
+ },
+ pull: function pull(controller) {
+ return reader.read().then(function (_ref2) {
+ var done = _ref2.done,
+ value = _ref2.value;
+
+ if (done) {
+ controller.enqueue(new Uint8Array([0x3b]));
+ controller.close();
+ return;
+ }
+
+ self.addFrame.apply(self, [controller].concat(value));
+ });
+ }
+ });
+ }
+
+ GifWriter.prototype.addFrame = function addFrame(controller, x, y, w, h, indexed_pixels) {
+ var opts = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
+
+ var p = 0;
+ var buf = [];
+
+ // TODO(deanm): Bounds check x, y. Do they need to be within the virtual
+ // canvas width/height, I imagine?
+ if (x < 0 || y < 0 || x > 65535 || y > 65535) {
+ throw new Error('x/y invalid.');
+ }
+
+ if (w <= 0 || h <= 0 || w > 65535 || h > 65535) throw "Width/Height invalid.";
+
+ if (indexed_pixels.length < w * h) throw "Not enough pixels for the frame size.";
+
+ var using_local_palette = true;
+ var palette = opts.palette;
+ if (palette === undefined || palette === null) {
+ using_local_palette = false;
+ palette = global_palette;
+ }
+
+ if (palette === undefined || palette === null) throw "Must supply either a local or global palette.";
+
+ var num_colors = check_palette_and_num_colors(palette);
+
+ // Compute the min_code_size (power of 2), destroying num_colors.
+ var min_code_size = 0;
+ while (num_colors >>= 1) {
+ ++min_code_size;
+ }num_colors = 1 << min_code_size; // Now we can easily get it back.
+
+ var delay = opts.delay === undefined ? 0 : opts.delay;
+
+ // From the spec:
+ // 0 - No disposal specified. The decoder is
+ // not required to take any action.
+ // 1 - Do not dispose. The graphic is to be left
+ // in place.
+ // 2 - Restore to background color. The area used by the
+ // graphic must be restored to the background color.
+ // 3 - Restore to previous. The decoder is required to
+ // restore the area overwritten by the graphic with
+ // what was there prior to rendering the graphic.
+ // 4-7 - To be defined.
+ // NOTE(deanm): Dispose background doesn't really work, apparently most
+ // browsers ignore the background palette index and clear to transparency.
+ var disposal = opts.disposal === undefined ? 0 : opts.disposal;
+ if (disposal < 0 || disposal > 3) // 4-7 is reserved.
+ throw "Disposal out of range.";
+
+ var use_transparency = false;
+ var transparent_index = 0;
+ if (opts.transparent !== undefined && opts.transparent !== null) {
+ use_transparency = true;
+ transparent_index = opts.transparent;
+ if (transparent_index < 0 || transparent_index >= num_colors) throw "Transparent color index.";
+ }
+
+ if (disposal !== 0 || use_transparency || delay !== 0) {
+ // - Graphics Control Extension
+ buf[p++] = 0x21;buf[p++] = 0xf9; // Extension / Label.
+ buf[p++] = 4; // Byte size.
+
+ buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0);
+ buf[p++] = delay & 0xff;buf[p++] = delay >> 8 & 0xff;
+ buf[p++] = transparent_index; // Transparent color index.
+ buf[p++] = 0; // Block Terminator.
+ }
+
+ // - Image Descriptor
+ buf[p++] = 0x2c; // Image Seperator.
+ buf[p++] = x & 0xff;buf[p++] = x >> 8 & 0xff; // Left.
+ buf[p++] = y & 0xff;buf[p++] = y >> 8 & 0xff; // Top.
+ buf[p++] = w & 0xff;buf[p++] = w >> 8 & 0xff;
+ buf[p++] = h & 0xff;buf[p++] = h >> 8 & 0xff;
+ // NOTE: No sort flag (unused?).
+ // TODO(deanm): Support interlace.
+ buf[p++] = using_local_palette === true ? 0x80 | min_code_size - 1 : 0;
+
+ // - Local Color Table
+ if (using_local_palette === true) {
+ for (var i = 0, il = palette.length; i < il; ++i) {
+ var rgb = palette[i];
+ buf[p++] = rgb >> 16 & 0xff;
+ buf[p++] = rgb >> 8 & 0xff;
+ buf[p++] = rgb & 0xff;
+ }
+ }
+
+ GifWriterOutputLZWCodeStream(buf, p, min_code_size < 2 ? 2 : min_code_size, indexed_pixels);
+
+ controller.enqueue(new Uint8Array(buf));
+ };
+
+ return GifWriter;
+}();
+
+// Main compression routine, palette indexes -> LZW code stream.
+// |index_stream| must have at least one entry.
+
+
+function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) {
+ buf[p++] = min_code_size;
+ var cur_subblock = p++; // Pointing at the length field.
+
+ var clear_code = 1 << min_code_size;
+ var code_mask = clear_code - 1;
+ var eoi_code = clear_code + 1;
+ var next_code = eoi_code + 1;
+
+ var cur_code_size = min_code_size + 1; // Number of bits per code.
+ var cur_shift = 0;
+ // We have at most 12-bit codes, so we should have to hold a max of 19
+ // bits here (and then we would write out).
+ var cur = 0;
+
+ function emit_bytes_to_buffer(bit_block_size) {
+ while (cur_shift >= bit_block_size) {
+ buf[p++] = cur & 0xff;
+ cur >>= 8;cur_shift -= 8;
+ if (p === cur_subblock + 256) {
+ // Finished a subblock.
+ buf[cur_subblock] = 255;
+ cur_subblock = p++;
+ }
+ }
+ }
+
+ function emit_code(c) {
+ cur |= c << cur_shift;
+ cur_shift += cur_code_size;
+ emit_bytes_to_buffer(8);
+ }
+
+ // I am not an expert on the topic, and I don't want to write a thesis.
+ // However, it is good to outline here the basic algorithm and the few data
+ // structures and optimizations here that make this implementation fast.
+ // The basic idea behind LZW is to build a table of previously seen runs
+ // addressed by a short id (herein called output code). All data is
+ // referenced by a code, which represents one or more values from the
+ // original input stream. All input bytes can be referenced as the same
+ // value as an output code. So if you didn't want any compression, you
+ // could more or less just output the original bytes as codes (there are
+ // some details to this, but it is the idea). In order to achieve
+ // compression, values greater then the input range (codes can be up to
+ // 12-bit while input only 8-bit) represent a sequence of previously seen
+ // inputs. The decompressor is able to build the same mapping while
+ // decoding, so there is always a shared common knowledge between the
+ // encoding and decoder, which is also important for "timing" aspects like
+ // how to handle variable bit width code encoding.
+ //
+ // One obvious but very important consequence of the table system is there
+ // is always a unique id (at most 12-bits) to map the runs. 'A' might be
+ // 4, then 'AA' might be 10, 'AAA' 11, 'AAAA' 12, etc. This relationship
+ // can be used for an effecient lookup strategy for the code mapping. We
+ // need to know if a run has been seen before, and be able to map that run
+ // to the output code. Since we start with known unique ids (input bytes),
+ // and then from those build more unique ids (table entries), we can
+ // continue this chain (almost like a linked list) to always have small
+ // integer values that represent the current byte chains in the encoder.
+ // This means instead of tracking the input bytes (AAAABCD) to know our
+ // current state, we can track the table entry for AAAABC (it is guaranteed
+ // to exist by the nature of the algorithm) and the next character D.
+ // Therefor the tuple of (table_entry, byte) is guaranteed to also be
+ // unique. This allows us to create a simple lookup key for mapping input
+ // sequences to codes (table indices) without having to store or search
+ // any of the code sequences. So if 'AAAA' has a table entry of 12, the
+ // tuple of ('AAAA', K) for any input byte K will be unique, and can be our
+ // key. This leads to a integer value at most 20-bits, which can always
+ // fit in an SMI value and be used as a fast sparse array / object key.
+
+ // Output code for the current contents of the index buffer.
+ var ib_code = index_stream[0] & code_mask; // Load first input index.
+ var code_table = {}; // Key'd on our 20-bit "tuple".
+
+ emit_code(clear_code); // Spec says first code should be a clear code.
+
+ // First index already loaded, process the rest of the stream.
+ for (var i = 1, il = index_stream.length; i < il; ++i) {
+ var k = index_stream[i] & code_mask;
+ var cur_key = ib_code << 8 | k; // (prev, k) unique tuple.
+ var cur_code = code_table[cur_key]; // buffer + k.
+
+ // Check if we have to create a new code table entry.
+ if (cur_code === undefined) {
+ // We don't have buffer + k.
+ // Emit index buffer (without k).
+ // This is an inline version of emit_code, because this is the core
+ // writing routine of the compressor (and V8 cannot inline emit_code
+ // because it is a closure here in a different context). Additionally
+ // we can call emit_byte_to_buffer less often, because we can have
+ // 30-bits (from our 31-bit signed SMI), and we know our codes will only
+ // be 12-bits, so can safely have 18-bits there without overflow.
+ // emit_code(ib_code);
+ cur |= ib_code << cur_shift;
+ cur_shift += cur_code_size;
+ while (cur_shift >= 8) {
+ buf[p++] = cur & 0xff;
+ cur >>= 8;cur_shift -= 8;
+ if (p === cur_subblock + 256) {
+ // Finished a subblock.
+ buf[cur_subblock] = 255;
+ cur_subblock = p++;
+ }
+ }
+
+ if (next_code === 4096) {
+ // Table full, need a clear.
+ emit_code(clear_code);
+ next_code = eoi_code + 1;
+ cur_code_size = min_code_size + 1;
+ code_table = {};
+ } else {
+ // Table not full, insert a new entry.
+ // Increase our variable bit code sizes if necessary. This is a bit
+ // tricky as it is based on "timing" between the encoding and
+ // decoder. From the encoders perspective this should happen after
+ // we've already emitted the index buffer and are about to create the
+ // first table entry that would overflow our current code bit size.
+ if (next_code >= 1 << cur_code_size) ++cur_code_size;
+ code_table[cur_key] = next_code++; // Insert into code table.
+ }
+
+ ib_code = k; // Index buffer to single input k.
+ } else {
+ ib_code = cur_code; // Index buffer to sequence in code table.
+ }
+ }
+
+ emit_code(ib_code); // There will still be something in the index buffer.
+ emit_code(eoi_code); // End Of Information.
+
+ // Flush / finalize the sub-blocks stream to the buffer.
+ emit_bytes_to_buffer(1);
+
+ // Finish the sub-blocks, writing out any unfinished lengths and
+ // terminating with a sub-block of length 0. If we have already started
+ // but not yet used a sub-block it can just become the terminator.
+ if (cur_subblock + 1 === p) {
+ // Started but unused.
+ buf[cur_subblock] = 0;
+ } else {
+ // Started and used, write length and additional terminator block.
+ buf[cur_subblock] = p - cur_subblock - 1;
+ buf[p++] = 0;
+ }
+ return p;
+}
diff --git a/www/external/imagesloaded.pkgd.js b/www/external/origjs/imagesloaded.pkgd.js
index ef23971b..ef23971b 100644
--- a/www/external/imagesloaded.pkgd.js
+++ b/www/external/origjs/imagesloaded.pkgd.js
diff --git a/www/external/ion-pullup.js b/www/external/origjs/ion-pullup.js
index ae9109a8..ae9109a8 100755
--- a/www/external/ion-pullup.js
+++ b/www/external/origjs/ion-pullup.js
diff --git a/www/external/ionRadio.js b/www/external/origjs/ionRadio.js
index cb240b76..cb240b76 100644
--- a/www/external/ionRadio.js
+++ b/www/external/origjs/ionRadio.js
diff --git a/www/external/ionic.content.banner.js b/www/external/origjs/ionic.content.banner.js
index 900b96a6..900b96a6 100644
--- a/www/external/ionic.content.banner.js
+++ b/www/external/origjs/ionic.content.banner.js
diff --git a/www/external/ionic.scroll.sista.js b/www/external/origjs/ionic.scroll.sista.js
index f8dd8143..f8dd8143 100644
--- a/www/external/ionic.scroll.sista.js
+++ b/www/external/origjs/ionic.scroll.sista.js
diff --git a/www/external/ng-websocket.js b/www/external/origjs/ng-websocket.js
index 02f92d2b..02f92d2b 100644
--- a/www/external/ng-websocket.js
+++ b/www/external/origjs/ng-websocket.js
diff --git a/www/external/packery.pkgd.js b/www/external/origjs/packery.pkgd.js
index 7576576b..7576576b 100644
--- a/www/external/packery.pkgd.js
+++ b/www/external/origjs/packery.pkgd.js
diff --git a/www/external/packery.pkgd.min.js b/www/external/packery.pkgd.min.js
new file mode 100644
index 00000000..f1ba5e03
--- /dev/null
+++ b/www/external/packery.pkgd.min.js
@@ -0,0 +1,270 @@
+/*!
+ * Packery PACKAGED v2.0.0
+ * Gapless, draggable grid layouts
+ *
+ * Licensed GPLv3 for open source use
+ * or Packery Commercial License for commercial use
+ *
+ * http://packery.metafizzy.co
+ * Copyright 2016 Metafizzy
+ */
+!function(t,e){"use strict"
+"function"==typeof define&&define.amd?define("jquery-bridget/jquery-bridget",["jquery"],function(i){e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("jquery")):t.jQueryBridget=e(t,t.jQuery)}(window,function(t,e){"use strict"
+function i(i,s,a){function h(t,e,n){var o,s="$()."+i+'("'+e+'")'
+return t.each(function(t,h){var u=a.data(h,i)
+if(!u)return void r(i+" not initialized. Cannot call methods, i.e. "+s)
+var c=u[e]
+if(!c||"_"==e.charAt(0))return void r(s+" is not a valid method")
+var d=c.apply(u,n)
+o=void 0===o?d:o}),void 0!==o?o:t}function u(t,e){t.each(function(t,n){var o=a.data(n,i)
+o?(o.option(e),o._init()):(o=new s(n,e),a.data(n,i,o))})}a=a||e||t.jQuery,a&&(s.prototype.option||(s.prototype.option=function(t){a.isPlainObject(t)&&(this.options=a.extend(!0,this.options,t))}),a.fn[i]=function(t){if("string"==typeof t){var e=o.call(arguments,1)
+return h(this,t,e)}return u(this,t),this},n(a))}function n(t){!t||t&&t.bridget||(t.bridget=i)}var o=Array.prototype.slice,s=t.console,r="undefined"==typeof s?function(){}:function(t){s.error(t)}
+return n(e||t.jQuery),i}),function(t,e){"use strict"
+"function"==typeof define&&define.amd?define("get-size/get-size",[],function(){return e()}):"object"==typeof module&&module.exports?module.exports=e():t.getSize=e()}(window,function(){"use strict"
+function t(t){var e=parseFloat(t),i=t.indexOf("%")==-1&&!isNaN(e)
+return i&&e}function e(){}function i(){for(var t={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},e=0;e<u;e++){var i=h[e]
+t[i]=0}return t}function n(t){var e=getComputedStyle(t)
+return e||a("Style returned "+e+". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1"),e}function o(){if(!c){c=!0
+var e=document.createElement("div")
+e.style.width="200px",e.style.padding="1px 2px 3px 4px",e.style.borderStyle="solid",e.style.borderWidth="1px 2px 3px 4px",e.style.boxSizing="border-box"
+var i=document.body||document.documentElement
+i.appendChild(e)
+var o=n(e)
+s.isBoxSizeOuter=r=200==Math.round(t(o.width)),i.removeChild(e)}}function s(e){if(o(),"string"==typeof e&&(e=document.querySelector(e)),e&&"object"==typeof e&&e.nodeType){var s=n(e)
+if("none"==s.display)return i()
+var a={}
+a.width=e.offsetWidth,a.height=e.offsetHeight
+for(var c=a.isBorderBox="border-box"==s.boxSizing,d=0;d<u;d++){var l=h[d],f=s[l],p=parseFloat(f)
+a[l]=isNaN(p)?0:p}var m=a.paddingLeft+a.paddingRight,g=a.paddingTop+a.paddingBottom,y=a.marginLeft+a.marginRight,v=a.marginTop+a.marginBottom,x=a.borderLeftWidth+a.borderRightWidth,_=a.borderTopWidth+a.borderBottomWidth,b=c&&r,E=t(s.width)
+E!==!1&&(a.width=E+(b?0:m+x))
+var z=t(s.height)
+return z!==!1&&(a.height=z+(b?0:g+_)),a.innerWidth=a.width-(m+x),a.innerHeight=a.height-(g+_),a.outerWidth=a.width+y,a.outerHeight=a.height+v,a}}var r,a="undefined"==typeof console?e:function(t){console.error(t)},h=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"],u=h.length,c=!1
+return s}),function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}(this,function(){function t(){}var e=t.prototype
+return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[]
+return n.indexOf(e)==-1&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e)
+var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||{}
+return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t]
+if(i&&i.length){var n=i.indexOf(e)
+return n!=-1&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t]
+if(i&&i.length){var n=0,o=i[n]
+e=e||[]
+for(var s=this._onceEvents&&this._onceEvents[t];o;){var r=s&&s[o]
+r&&(this.off(t,o),delete s[o]),o.apply(this,e),n+=r?0:1,o=i[n]}return this}},t}),function(t,e){"use strict"
+"function"==typeof define&&define.amd?define("desandro-matches-selector/matches-selector",e):"object"==typeof module&&module.exports?module.exports=e():t.matchesSelector=e()}(window,function(){"use strict"
+var t=function(){var t=Element.prototype
+if(t.matches)return"matches"
+if(t.matchesSelector)return"matchesSelector"
+for(var e=["webkit","moz","ms","o"],i=0;i<e.length;i++){var n=e[i],o=n+"MatchesSelector"
+if(t[o])return o}}()
+return function(e,i){return e[t](i)}}),function(t,e){"function"==typeof define&&define.amd?define("fizzy-ui-utils/utils",["desandro-matches-selector/matches-selector"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("desandro-matches-selector")):t.fizzyUIUtils=e(t,t.matchesSelector)}(window,function(t,e){var i={}
+i.extend=function(t,e){for(var i in e)t[i]=e[i]
+return t},i.modulo=function(t,e){return(t%e+e)%e},i.makeArray=function(t){var e=[]
+if(Array.isArray(t))e=t
+else if(t&&"number"==typeof t.length)for(var i=0;i<t.length;i++)e.push(t[i])
+else e.push(t)
+return e},i.removeFrom=function(t,e){var i=t.indexOf(e)
+i!=-1&&t.splice(i,1)},i.getParent=function(t,i){for(;t!=document.body;)if(t=t.parentNode,e(t,i))return t},i.getQueryElement=function(t){return"string"==typeof t?document.querySelector(t):t},i.handleEvent=function(t){var e="on"+t.type
+this[e]&&this[e](t)},i.filterFindElements=function(t,n){t=i.makeArray(t)
+var o=[]
+return t.forEach(function(t){if(t instanceof HTMLElement){if(!n)return void o.push(t)
+e(t,n)&&o.push(t)
+for(var i=t.querySelectorAll(n),s=0;s<i.length;s++)o.push(i[s])}}),o},i.debounceMethod=function(t,e,i){var n=t.prototype[e],o=e+"Timeout"
+t.prototype[e]=function(){var t=this[o]
+t&&clearTimeout(t)
+var e=arguments,s=this
+this[o]=setTimeout(function(){n.apply(s,e),delete s[o]},i||100)}},i.docReady=function(t){"complete"==document.readyState?t():document.addEventListener("DOMContentLoaded",t)},i.toDashed=function(t){return t.replace(/(.)([A-Z])/g,function(t,e,i){return e+"-"+i}).toLowerCase()}
+var n=t.console
+return i.htmlInit=function(e,o){i.docReady(function(){var s=i.toDashed(o),r="data-"+s,a=document.querySelectorAll("["+r+"]"),h=document.querySelectorAll(".js-"+s),u=i.makeArray(a).concat(i.makeArray(h)),c=r+"-options",d=t.jQuery
+u.forEach(function(t){var i,s=t.getAttribute(r)||t.getAttribute(c)
+try{i=s&&JSON.parse(s)}catch(e){return void(n&&n.error("Error parsing "+r+" on "+t.className+": "+e))}var a=new e(t,i)
+d&&d.data(t,o,a)})})},i}),function(t,e){"function"==typeof define&&define.amd?define("outlayer/item",["ev-emitter/ev-emitter","get-size/get-size"],e):"object"==typeof module&&module.exports?module.exports=e(require("ev-emitter"),require("get-size")):(t.Outlayer={},t.Outlayer.Item=e(t.EvEmitter,t.getSize))}(window,function(t,e){"use strict"
+function i(t){for(var e in t)return!1
+return e=null,!0}function n(t,e){t&&(this.element=t,this.layout=e,this.position={x:0,y:0},this._create())}function o(t){return t.replace(/([A-Z])/g,function(t){return"-"+t.toLowerCase()})}var s=document.documentElement.style,r="string"==typeof s.transition?"transition":"WebkitTransition",a="string"==typeof s.transform?"transform":"WebkitTransform",h={WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[r],u={transform:a,transition:r,transitionDuration:r+"Duration",transitionProperty:r+"Property"},c=n.prototype=Object.create(t.prototype)
+c.constructor=n,c._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"})},c.handleEvent=function(t){var e="on"+t.type
+this[e]&&this[e](t)},c.getSize=function(){this.size=e(this.element)},c.css=function(t){var e=this.element.style
+for(var i in t){var n=u[i]||i
+e[n]=t[i]}},c.getPosition=function(){var t=getComputedStyle(this.element),e=this.layout._getOption("originLeft"),i=this.layout._getOption("originTop"),n=t[e?"left":"right"],o=t[i?"top":"bottom"],s=this.layout.size,r=n.indexOf("%")!=-1?parseFloat(n)/100*s.width:parseInt(n,10),a=o.indexOf("%")!=-1?parseFloat(o)/100*s.height:parseInt(o,10)
+r=isNaN(r)?0:r,a=isNaN(a)?0:a,r-=e?s.paddingLeft:s.paddingRight,a-=i?s.paddingTop:s.paddingBottom,this.position.x=r,this.position.y=a},c.layoutPosition=function(){var t=this.layout.size,e={},i=this.layout._getOption("originLeft"),n=this.layout._getOption("originTop"),o=i?"paddingLeft":"paddingRight",s=i?"left":"right",r=i?"right":"left",a=this.position.x+t[o]
+e[s]=this.getXValue(a),e[r]=""
+var h=n?"paddingTop":"paddingBottom",u=n?"top":"bottom",c=n?"bottom":"top",d=this.position.y+t[h]
+e[u]=this.getYValue(d),e[c]="",this.css(e),this.emitEvent("layout",[this])},c.getXValue=function(t){var e=this.layout._getOption("horizontal")
+return this.layout.options.percentPosition&&!e?t/this.layout.size.width*100+"%":t+"px"},c.getYValue=function(t){var e=this.layout._getOption("horizontal")
+return this.layout.options.percentPosition&&e?t/this.layout.size.height*100+"%":t+"px"},c._transitionTo=function(t,e){this.getPosition()
+var i=this.position.x,n=this.position.y,o=parseInt(t,10),s=parseInt(e,10),r=o===this.position.x&&s===this.position.y
+if(this.setPosition(t,e),r&&!this.isTransitioning)return void this.layoutPosition()
+var a=t-i,h=e-n,u={}
+u.transform=this.getTranslate(a,h),this.transition({to:u,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},c.getTranslate=function(t,e){var i=this.layout._getOption("originLeft"),n=this.layout._getOption("originTop")
+return t=i?t:-t,e=n?e:-e,"translate3d("+t+"px, "+e+"px, 0)"},c.goTo=function(t,e){this.setPosition(t,e),this.layoutPosition()},c.moveTo=c._transitionTo,c.setPosition=function(t,e){this.position.x=parseInt(t,10),this.position.y=parseInt(e,10)},c._nonTransition=function(t){this.css(t.to),t.isCleaning&&this._removeStyles(t.to)
+for(var e in t.onTransitionEnd)t.onTransitionEnd[e].call(this)},c.transition=function(t){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(t)
+var e=this._transn
+for(var i in t.onTransitionEnd)e.onEnd[i]=t.onTransitionEnd[i]
+for(i in t.to)e.ingProperties[i]=!0,t.isCleaning&&(e.clean[i]=!0)
+if(t.from){this.css(t.from)
+var n=this.element.offsetHeight
+n=null}this.enableTransition(t.to),this.css(t.to),this.isTransitioning=!0}
+var d="opacity,"+o(a)
+c.enableTransition=function(){this.isTransitioning||(this.css({transitionProperty:d,transitionDuration:this.layout.options.transitionDuration}),this.element.addEventListener(h,this,!1))},c.onwebkitTransitionEnd=function(t){this.ontransitionend(t)},c.onotransitionend=function(t){this.ontransitionend(t)}
+var l={"-webkit-transform":"transform"}
+c.ontransitionend=function(t){if(t.target===this.element){var e=this._transn,n=l[t.propertyName]||t.propertyName
+if(delete e.ingProperties[n],i(e.ingProperties)&&this.disableTransition(),n in e.clean&&(this.element.style[t.propertyName]="",delete e.clean[n]),n in e.onEnd){var o=e.onEnd[n]
+o.call(this),delete e.onEnd[n]}this.emitEvent("transitionEnd",[this])}},c.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(h,this,!1),this.isTransitioning=!1},c._removeStyles=function(t){var e={}
+for(var i in t)e[i]=""
+this.css(e)}
+var f={transitionProperty:"",transitionDuration:""}
+return c.removeTransitionStyles=function(){this.css(f)},c.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:""}),this.emitEvent("remove",[this])},c.remove=function(){return r&&parseFloat(this.layout.options.transitionDuration)?(this.once("transitionEnd",function(){this.removeElem()}),void this.hide()):void this.removeElem()},c.reveal=function(){delete this.isHidden,this.css({display:""})
+var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("visibleStyle")
+e[i]=this.onRevealTransitionEnd,this.transition({from:t.hiddenStyle,to:t.visibleStyle,isCleaning:!0,onTransitionEnd:e})},c.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent("reveal")},c.getHideRevealTransitionEndProperty=function(t){var e=this.layout.options[t]
+if(e.opacity)return"opacity"
+for(var i in e)return i},c.hide=function(){this.isHidden=!0,this.css({display:""})
+var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("hiddenStyle")
+e[i]=this.onHideTransitionEnd,this.transition({from:t.visibleStyle,to:t.hiddenStyle,isCleaning:!0,onTransitionEnd:e})},c.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:"none"}),this.emitEvent("hide"))},c.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""})},n}),function(t,e){"use strict"
+"function"==typeof define&&define.amd?define("outlayer/outlayer",["ev-emitter/ev-emitter","get-size/get-size","fizzy-ui-utils/utils","./item"],function(i,n,o,s){return e(t,i,n,o,s)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter"),require("get-size"),require("fizzy-ui-utils"),require("./item")):t.Outlayer=e(t,t.EvEmitter,t.getSize,t.fizzyUIUtils,t.Outlayer.Item)}(window,function(t,e,i,n,o){"use strict"
+function s(t,e){var i=n.getQueryElement(t)
+if(!i)return void(a&&a.error("Bad element for "+this.constructor.namespace+": "+(i||t)))
+this.element=i,h&&(this.$element=h(this.element)),this.options=n.extend({},this.constructor.defaults),this.option(e)
+var o=++c
+this.element.outlayerGUID=o,d[o]=this,this._create()
+var s=this._getOption("initLayout")
+s&&this.layout()}function r(t){function e(){t.apply(this,arguments)}return e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e}var a=t.console,h=t.jQuery,u=function(){},c=0,d={}
+s.namespace="outlayer",s.Item=o,s.defaults={containerStyle:{position:"relative"},initLayout:!0,originLeft:!0,originTop:!0,resize:!0,resizeContainer:!0,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}}
+var l=s.prototype
+return n.extend(l,e.prototype),l.option=function(t){n.extend(this.options,t)},l._getOption=function(t){var e=this.constructor.compatOptions[t]
+return e&&void 0!==this.options[e]?this.options[e]:this.options[t]},s.compatOptions={initLayout:"isInitLayout",horizontal:"isHorizontal",layoutInstant:"isLayoutInstant",originLeft:"isOriginLeft",originTop:"isOriginTop",resize:"isResizeBound",resizeContainer:"isResizingContainer"},l._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),n.extend(this.element.style,this.options.containerStyle)
+var t=this._getOption("resize")
+t&&this.bindResize()},l.reloadItems=function(){this.items=this._itemize(this.element.children)},l._itemize=function(t){for(var e=this._filterFindItemElements(t),i=this.constructor.Item,n=[],o=0;o<e.length;o++){var s=e[o],r=new i(s,this)
+n.push(r)}return n},l._filterFindItemElements=function(t){return n.filterFindElements(t,this.options.itemSelector)},l.getItemElements=function(){return this.items.map(function(t){return t.element})},l.layout=function(){this._resetLayout(),this._manageStamps()
+var t=this._getOption("layoutInstant"),e=void 0!==t?t:!this._isLayoutInited
+this.layoutItems(this.items,e),this._isLayoutInited=!0},l._init=l.layout,l._resetLayout=function(){this.getSize()},l.getSize=function(){this.size=i(this.element)},l._getMeasurement=function(t,e){var n,o=this.options[t]
+o?("string"==typeof o?n=this.element.querySelector(o):o instanceof HTMLElement&&(n=o),this[t]=n?i(n)[e]:o):this[t]=0},l.layoutItems=function(t,e){t=this._getItemsForLayout(t),this._layoutItems(t,e),this._postLayout()},l._getItemsForLayout=function(t){return t.filter(function(t){return!t.isIgnored})},l._layoutItems=function(t,e){if(this._emitCompleteOnItems("layout",t),t&&t.length){var i=[]
+t.forEach(function(t){var n=this._getItemLayoutPosition(t)
+n.item=t,n.isInstant=e||t.isLayoutInstant,i.push(n)},this),this._processLayoutQueue(i)}},l._getItemLayoutPosition=function(){return{x:0,y:0}},l._processLayoutQueue=function(t){t.forEach(function(t){this._positionItem(t.item,t.x,t.y,t.isInstant)},this)},l._positionItem=function(t,e,i,n){n?t.goTo(e,i):t.moveTo(e,i)},l._postLayout=function(){this.resizeContainer()},l.resizeContainer=function(){var t=this._getOption("resizeContainer")
+if(t){var e=this._getContainerSize()
+e&&(this._setContainerMeasure(e.width,!0),this._setContainerMeasure(e.height,!1))}},l._getContainerSize=u,l._setContainerMeasure=function(t,e){if(void 0!==t){var i=this.size
+i.isBorderBox&&(t+=e?i.paddingLeft+i.paddingRight+i.borderLeftWidth+i.borderRightWidth:i.paddingBottom+i.paddingTop+i.borderTopWidth+i.borderBottomWidth),t=Math.max(t,0),this.element.style[e?"width":"height"]=t+"px"}},l._emitCompleteOnItems=function(t,e){function i(){o.dispatchEvent(t+"Complete",null,[e])}function n(){r++,r==s&&i()}var o=this,s=e.length
+if(!e||!s)return void i()
+var r=0
+e.forEach(function(e){e.once(t,n)})},l.dispatchEvent=function(t,e,i){var n=e?[e].concat(i):i
+if(this.emitEvent(t,n),h)if(this.$element=this.$element||h(this.element),e){var o=h.Event(e)
+o.type=t,this.$element.trigger(o,i)}else this.$element.trigger(t,i)},l.ignore=function(t){var e=this.getItem(t)
+e&&(e.isIgnored=!0)},l.unignore=function(t){var e=this.getItem(t)
+e&&delete e.isIgnored},l.stamp=function(t){t=this._find(t),t&&(this.stamps=this.stamps.concat(t),t.forEach(this.ignore,this))},l.unstamp=function(t){t=this._find(t),t&&t.forEach(function(t){n.removeFrom(this.stamps,t),this.unignore(t)},this)},l._find=function(t){if(t)return"string"==typeof t&&(t=this.element.querySelectorAll(t)),t=n.makeArray(t)},l._manageStamps=function(){this.stamps&&this.stamps.length&&(this._getBoundingRect(),this.stamps.forEach(this._manageStamp,this))},l._getBoundingRect=function(){var t=this.element.getBoundingClientRect(),e=this.size
+this._boundingRect={left:t.left+e.paddingLeft+e.borderLeftWidth,top:t.top+e.paddingTop+e.borderTopWidth,right:t.right-(e.paddingRight+e.borderRightWidth),bottom:t.bottom-(e.paddingBottom+e.borderBottomWidth)}},l._manageStamp=u,l._getElementOffset=function(t){var e=t.getBoundingClientRect(),n=this._boundingRect,o=i(t),s={left:e.left-n.left-o.marginLeft,top:e.top-n.top-o.marginTop,right:n.right-e.right-o.marginRight,bottom:n.bottom-e.bottom-o.marginBottom}
+return s},l.handleEvent=n.handleEvent,l.bindResize=function(){t.addEventListener("resize",this),this.isResizeBound=!0},l.unbindResize=function(){t.removeEventListener("resize",this),this.isResizeBound=!1},l.onresize=function(){this.resize()},n.debounceMethod(s,"onresize",100),l.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},l.needsResizeLayout=function(){var t=i(this.element),e=this.size&&t
+return e&&t.innerWidth!==this.size.innerWidth},l.addItems=function(t){var e=this._itemize(t)
+return e.length&&(this.items=this.items.concat(e)),e},l.appended=function(t){var e=this.addItems(t)
+e.length&&(this.layoutItems(e,!0),this.reveal(e))},l.prepended=function(t){var e=this._itemize(t)
+if(e.length){var i=this.items.slice(0)
+this.items=e.concat(i),this._resetLayout(),this._manageStamps(),this.layoutItems(e,!0),this.reveal(e),this.layoutItems(i)}},l.reveal=function(t){this._emitCompleteOnItems("reveal",t),t&&t.length&&t.forEach(function(t){t.reveal()})},l.hide=function(t){this._emitCompleteOnItems("hide",t),t&&t.length&&t.forEach(function(t){t.hide()})},l.revealItemElements=function(t){var e=this.getItems(t)
+this.reveal(e)},l.hideItemElements=function(t){var e=this.getItems(t)
+this.hide(e)},l.getItem=function(t){for(var e=0;e<this.items.length;e++){var i=this.items[e]
+if(i.element==t)return i}},l.getItems=function(t){t=n.makeArray(t)
+var e=[]
+return t.forEach(function(t){var i=this.getItem(t)
+i&&e.push(i)},this),e},l.remove=function(t){var e=this.getItems(t)
+this._emitCompleteOnItems("remove",e),e&&e.length&&e.forEach(function(t){t.remove(),n.removeFrom(this.items,t)},this)},l.destroy=function(){var t=this.element.style
+t.height="",t.position="",t.width="",this.items.forEach(function(t){t.destroy()}),this.unbindResize()
+var e=this.element.outlayerGUID
+delete d[e],delete this.element.outlayerGUID,h&&h.removeData(this.element,this.constructor.namespace)},s.data=function(t){t=n.getQueryElement(t)
+var e=t&&t.outlayerGUID
+return e&&d[e]},s.create=function(t,e){var i=r(s)
+return i.defaults=n.extend({},s.defaults),n.extend(i.defaults,e),i.compatOptions=n.extend({},s.compatOptions),i.namespace=t,i.data=s.data,i.Item=r(o),n.htmlInit(i,t),h&&h.bridget&&h.bridget(t,i),i},s.Item=o,s}),function(t,e){"function"==typeof define&&define.amd?define("packery/rect",e):"object"==typeof module&&module.exports?module.exports=e():(t.Packery=t.Packery||{},t.Packery.Rect=e())}(window,function(){"use strict"
+function t(e){for(var i in t.defaults)this[i]=t.defaults[i]
+for(i in e)this[i]=e[i]}t.defaults={x:0,y:0,width:0,height:0}
+var e=t.prototype
+return e.contains=function(t){var e=t.width||0,i=t.height||0
+return this.x<=t.x&&this.y<=t.y&&this.x+this.width>=t.x+e&&this.y+this.height>=t.y+i},e.overlaps=function(t){var e=this.x+this.width,i=this.y+this.height,n=t.x+t.width,o=t.y+t.height
+return this.x<n&&e>t.x&&this.y<o&&i>t.y},e.getMaximalFreeRects=function(e){if(!this.overlaps(e))return!1
+var i,n=[],o=this.x+this.width,s=this.y+this.height,r=e.x+e.width,a=e.y+e.height
+return this.y<e.y&&(i=new t({x:this.x,y:this.y,width:this.width,height:e.y-this.y}),n.push(i)),o>r&&(i=new t({x:r,y:this.y,width:o-r,height:this.height}),n.push(i)),s>a&&(i=new t({x:this.x,y:a,width:this.width,height:s-a}),n.push(i)),this.x<e.x&&(i=new t({x:this.x,y:this.y,width:e.x-this.x,height:this.height}),n.push(i)),n},e.canFit=function(t){return this.width>=t.width&&this.height>=t.height},t}),function(t,e){if("function"==typeof define&&define.amd)define("packery/packer",["./rect"],e)
+else if("object"==typeof module&&module.exports)module.exports=e(require("./rect"))
+else{var i=t.Packery=t.Packery||{}
+i.Packer=e(i.Rect)}}(window,function(t){"use strict"
+function e(t,e,i){this.width=t||0,this.height=e||0,this.sortDirection=i||"downwardLeftToRight",this.reset()}var i=e.prototype
+i.reset=function(){this.spaces=[]
+var e=new t({x:0,y:0,width:this.width,height:this.height})
+this.spaces.push(e),this.sorter=n[this.sortDirection]||n.downwardLeftToRight},i.pack=function(t){for(var e=0;e<this.spaces.length;e++){var i=this.spaces[e]
+if(i.canFit(t)){this.placeInSpace(t,i)
+break}}},i.columnPack=function(t){for(var e=0;e<this.spaces.length;e++){var i=this.spaces[e],n=i.x<=t.x&&i.x+i.width>=t.x+t.width&&i.height>=t.height-.01
+if(n){t.y=i.y,this.placed(t)
+break}}},i.rowPack=function(t){for(var e=0;e<this.spaces.length;e++){var i=this.spaces[e],n=i.y<=t.y&&i.y+i.height>=t.y+t.height&&i.width>=t.width-.01
+if(n){t.x=i.x,this.placed(t)
+break}}},i.placeInSpace=function(t,e){t.x=e.x,t.y=e.y,this.placed(t)},i.placed=function(t){for(var e=[],i=0;i<this.spaces.length;i++){var n=this.spaces[i],o=n.getMaximalFreeRects(t)
+o?e.push.apply(e,o):e.push(n)}this.spaces=e,this.mergeSortSpaces()},i.mergeSortSpaces=function(){e.mergeRects(this.spaces),this.spaces.sort(this.sorter)},i.addSpace=function(t){this.spaces.push(t),this.mergeSortSpaces()},e.mergeRects=function(t){var e=0,i=t[e]
+t:for(;i;){for(var n=0,o=t[e+n];o;){if(o==i)n++
+else{if(o.contains(i)){t.splice(e,1),i=t[e]
+continue t}i.contains(o)?t.splice(e+n,1):n++}o=t[e+n]}e++,i=t[e]}return t}
+var n={downwardLeftToRight:function(t,e){return t.y-e.y||t.x-e.x},rightwardTopToBottom:function(t,e){return t.x-e.x||t.y-e.y}}
+return e}),function(t,e){"function"==typeof define&&define.amd?define("packery/item",["outlayer/outlayer","./rect"],e):"object"==typeof module&&module.exports?module.exports=e(require("outlayer"),require("./rect")):t.Packery.Item=e(t.Outlayer,t.Packery.Rect)}(window,function(t,e){"use strict"
+var i=document.documentElement.style,n="string"==typeof i.transform?"transform":"WebkitTransform",o=function(){t.Item.apply(this,arguments)},s=o.prototype=Object.create(t.Item.prototype),r=s._create
+s._create=function(){r.call(this),this.rect=new e}
+var a=s.moveTo
+return s.moveTo=function(t,e){var i=Math.abs(this.position.x-t),n=Math.abs(this.position.y-e),o=this.layout.dragItemCount&&!this.isPlacing&&!this.isTransitioning&&i<1&&n<1
+return o?void this.goTo(t,e):void a.apply(this,arguments)},s.enablePlacing=function(){this.removeTransitionStyles(),this.isTransitioning&&n&&(this.element.style[n]="none"),this.isTransitioning=!1,this.getSize(),this.layout._setRectSize(this.element,this.rect),this.isPlacing=!0},s.disablePlacing=function(){this.isPlacing=!1},s.removeElem=function(){this.element.parentNode.removeChild(this.element),this.layout.packer.addSpace(this.rect),this.emitEvent("remove",[this])},s.showDropPlaceholder=function(){var t=this.dropPlaceholder
+t||(t=this.dropPlaceholder=document.createElement("div"),t.className="packery-drop-placeholder",t.style.position="absolute"),t.style.width=this.size.width+"px",t.style.height=this.size.height+"px",this.positionDropPlaceholder(),this.layout.element.appendChild(t)},s.positionDropPlaceholder=function(){this.dropPlaceholder.style[n]="translate("+this.rect.x+"px, "+this.rect.y+"px)"},s.hideDropPlaceholder=function(){this.layout.element.removeChild(this.dropPlaceholder)},o}),function(t,e){"function"==typeof define&&define.amd?define(["get-size/get-size","outlayer/outlayer","./rect","./packer","./item"],e):"object"==typeof module&&module.exports?module.exports=e(require("get-size"),require("outlayer"),require("./rect"),require("./packer"),require("./item")):t.Packery=e(t.getSize,t.Outlayer,t.Packery.Rect,t.Packery.Packer,t.Packery.Item)}(window,function(t,e,i,n,o){"use strict"
+function s(t,e){return t.position.y-e.position.y||t.position.x-e.position.x}function r(t,e){return t.position.x-e.position.x||t.position.y-e.position.y}function a(t,e){var i=e.x-t.x,n=e.y-t.y
+return Math.sqrt(i*i+n*n)}i.prototype.canFit=function(t){return this.width>=t.width-1&&this.height>=t.height-1}
+var h=e.create("packery")
+h.Item=o
+var u=h.prototype
+h.prototype.getShiftPositions=function(t){t=t||"id"
+var e=this
+return this.items.map(function(i){return{attr:i.element.getAttribute(t),size:i.element.getAttribute("data-item-size"),display:i.element.getAttribute("data-item-listdisplay"),x:i.rect.x/e.packer.width,y:i.rect.y/e.packer.height}})},h.prototype.EHgetShiftPositions=function(t){t=t||"id"
+var e=this
+return this.items.map(function(i){return{attr:i.element.getAttribute(t),size:i.element.getAttribute("eh-data-item-size"),display:i.element.getAttribute("eh-data-item-listdisplay"),x:i.rect.x/e.packer.width,y:i.rect.y/e.packer.height}})},h.prototype.initShiftLayout=function(t,e){if(!t)return void this.layout()
+if("string"==typeof t)try{t=JSON.parse(t)}catch(t){return console.error("JSON parse error: "+t),void this.layout()}e=e||"id",this._resetLayout(),this.items=t.map(function(t){var i="["+e+'="'+t.attr+'"]',n=this.element.querySelector(i),o=this.getItem(n)
+return o.rect.x=t.x*this.packer.width,o.rect.y=t.y*this.packer.height,o},this),this.shiftLayout()},u._create=function(){e.prototype._create.call(this),this.packer=new n,this.shiftPacker=new n,this.isEnabled=!0,this.dragItemCount=0
+var t=this
+this.handleDraggabilly={dragStart:function(){t.itemDragStart(this.element)},dragMove:function(){t.itemDragMove(this.element,this.position.x,this.position.y)},dragEnd:function(){t.itemDragEnd(this.element)}},this.handleUIDraggable={start:function(e,i){i&&t.itemDragStart(e.currentTarget)},drag:function(e,i){i&&t.itemDragMove(e.currentTarget,i.position.left,i.position.top)},stop:function(e,i){i&&t.itemDragEnd(e.currentTarget)}}},u._resetLayout=function(){this.getSize(),this._getMeasurements()
+var t,e,i
+this._getOption("horizontal")?(t=1/0,e=this.size.innerHeight+this.gutter,i="rightwardTopToBottom"):(t=this.size.innerWidth+this.gutter,e=1/0,i="downwardLeftToRight"),this.packer.width=this.shiftPacker.width=t,this.packer.height=this.shiftPacker.height=e,this.packer.sortDirection=this.shiftPacker.sortDirection=i,this.packer.reset(),this.maxY=0,this.maxX=0},u._getMeasurements=function(){this._getMeasurement("columnWidth","width"),this._getMeasurement("rowHeight","height"),this._getMeasurement("gutter","width")},u._getItemLayoutPosition=function(t){if(this._setRectSize(t.element,t.rect),this.isShifting||this.dragItemCount>0){var e=this._getPackMethod()
+this.packer[e](t.rect)}else this.packer.pack(t.rect)
+return this._setMaxXY(t.rect),t.rect},u.shiftLayout=function(){this.isShifting=!0,this.layout(),delete this.isShifting},u._getPackMethod=function(){return this._getOption("horizontal")?"rowPack":"columnPack"},u._setMaxXY=function(t){this.maxX=Math.max(t.x+t.width,this.maxX),this.maxY=Math.max(t.y+t.height,this.maxY)},u._setRectSize=function(e,i){var n=t(e),o=n.outerWidth,s=n.outerHeight;(o||s)&&(o=this._applyGridGutter(o,this.columnWidth),s=this._applyGridGutter(s,this.rowHeight)),i.width=Math.min(o,this.packer.width),i.height=Math.min(s,this.packer.height)},u._applyGridGutter=function(t,e){if(!e)return t+this.gutter
+e+=this.gutter
+var i=t%e,n=i&&i<1?"round":"ceil"
+return t=Math[n](t/e)*e},u._getContainerSize=function(){return this._getOption("horizontal")?{width:this.maxX-this.gutter}:{height:this.maxY-this.gutter}},u._manageStamp=function(t){var e,n=this.getItem(t)
+if(n&&n.isPlacing)e=n.rect
+else{var o=this._getElementOffset(t)
+e=new i({x:this._getOption("originLeft")?o.left:o.right,y:this._getOption("originTop")?o.top:o.bottom})}this._setRectSize(t,e),this.packer.placed(e),this._setMaxXY(e)},u.sortItemsByPosition=function(){var t=this._getOption("horizontal")?r:s
+this.items.sort(t)},u.fit=function(t,e,i){var n=this.getItem(t)
+n&&(this.stamp(n.element),n.enablePlacing(),this.updateShiftTargets(n),e=void 0===e?n.rect.x:e,i=void 0===i?n.rect.y:i,this.shift(n,e,i),this._bindFitEvents(n),n.moveTo(n.rect.x,n.rect.y),this.shiftLayout(),this.unstamp(n.element),this.sortItemsByPosition(),n.disablePlacing())},u._bindFitEvents=function(t){function e(){n++,2==n&&i.dispatchEvent("fitComplete",null,[t])}var i=this,n=0
+t.once("layout",e),this.once("layoutComplete",e)},u.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&(this.options.shiftPercentResize?this.resizeShiftPercentLayout():this.layout())},u.needsResizeLayout=function(){var e=t(this.element),i=this._getOption("horizontal")?"innerHeight":"innerWidth"
+return e[i]!=this.size[i]},u.resizeShiftPercentLayout=function(){var e=this._getItemsForLayout(this.items),i=this._getOption("horizontal"),n=i?"y":"x",o=i?"height":"width",s=i?"rowHeight":"columnWidth",r=i?"innerHeight":"innerWidth",a=this[s]
+if(a=a&&a+this.gutter){this._getMeasurements()
+var h=this[s]+this.gutter
+e.forEach(function(t){var e=Math.round(t.rect[n]/a)
+t.rect[n]=e*h})}else{var u=t(this.element)[r]+this.gutter,c=this.packer[o]
+e.forEach(function(t){t.rect[n]=t.rect[n]/c*u})}this.shiftLayout()},u.itemDragStart=function(t){if(this.isEnabled){this.stamp(t)
+var e=this.getItem(t)
+e&&(e.enablePlacing(),e.showDropPlaceholder(),this.dragItemCount++,this.updateShiftTargets(e))}},u.updateShiftTargets=function(t){this.shiftPacker.reset(),this._getBoundingRect()
+var e=this._getOption("originLeft"),n=this._getOption("originTop")
+this.stamps.forEach(function(t){var o=this.getItem(t)
+if(!o||!o.isPlacing){var s=this._getElementOffset(t),r=new i({x:e?s.left:s.right,y:n?s.top:s.bottom})
+this._setRectSize(t,r),this.shiftPacker.placed(r)}},this)
+var o=this._getOption("horizontal"),s=o?"rowHeight":"columnWidth",r=o?"height":"width"
+this.shiftTargetKeys=[],this.shiftTargets=[]
+var a,h=this[s]
+if(h=h&&h+this.gutter){var u=Math.ceil(t.rect[r]/h),c=Math.floor((this.shiftPacker[r]+this.gutter)/h)
+a=(c-u)*h
+for(var d=0;d<c;d++)this._addShiftTarget(d*h,0,a)}else a=this.shiftPacker[r]+this.gutter-t.rect[r],this._addShiftTarget(0,0,a)
+var l=this._getItemsForLayout(this.items),f=this._getPackMethod()
+l.forEach(function(t){var e=t.rect
+this._setRectSize(t.element,e),this.shiftPacker[f](e),this._addShiftTarget(e.x,e.y,a)
+var i=o?e.x+e.width:e.x,n=o?e.y:e.y+e.height
+if(this._addShiftTarget(i,n,a),h)for(var s=Math.round(e[r]/h),u=1;u<s;u++){var c=o?i:e.x+h*u,d=o?e.y+h*u:n
+this._addShiftTarget(c,d,a)}},this)},u._addShiftTarget=function(t,e,i){var n=this._getOption("horizontal")?e:t
+if(!(0!==n&&n>i)){var o=t+","+e,s=this.shiftTargetKeys.indexOf(o)!=-1
+s||(this.shiftTargetKeys.push(o),this.shiftTargets.push({x:t,y:e}))}},u.shift=function(t,e,i){var n,o=1/0,s={x:e,y:i}
+this.shiftTargets.forEach(function(t){var e=a(t,s)
+e<o&&(n=t,o=e)}),t.rect.x=n.x,t.rect.y=n.y}
+var c=120
+u.itemDragMove=function(t,e,i){function n(){s.shift(o,e,i),o.positionDropPlaceholder(),s.layout()}var o=this.isEnabled&&this.getItem(t)
+if(o){e-=this.size.paddingLeft,i-=this.size.paddingTop
+var s=this,r=new Date
+this._itemDragTime&&r-this._itemDragTime<c?(clearTimeout(this.dragTimeout),this.dragTimeout=setTimeout(n,c)):(n(),this._itemDragTime=r)}},u.itemDragEnd=function(t){function e(){n++,2==n&&(i.element.classList.remove("is-positioning-post-drag"),i.hideDropPlaceholder(),o.dispatchEvent("dragItemPositioned",null,[i]))}var i=this.isEnabled&&this.getItem(t)
+if(i){clearTimeout(this.dragTimeout),i.element.classList.add("is-positioning-post-drag")
+var n=0,o=this
+i.once("layout",e),this.once("layoutComplete",e),i.moveTo(i.rect.x,i.rect.y),this.layout(),this.dragItemCount=Math.max(0,this.dragItemCount-1),this.sortItemsByPosition(),i.disablePlacing(),this.unstamp(i.element)}},u.bindDraggabillyEvents=function(t){this._bindDraggabillyEvents(t,"on")},u.unbindDraggabillyEvents=function(t){this._bindDraggabillyEvents(t,"off")},u._bindDraggabillyEvents=function(t,e){var i=this.handleDraggabilly
+t[e]("dragStart",i.dragStart),t[e]("dragMove",i.dragMove),t[e]("dragEnd",i.dragEnd)},u.bindUIDraggableEvents=function(t){this._bindUIDraggableEvents(t,"on")},u.unbindUIDraggableEvents=function(t){this._bindUIDraggableEvents(t,"off")},u._bindUIDraggableEvents=function(t,e){var i=this.handleUIDraggable
+t[e]("dragstart",i.start)[e]("drag",i.drag)[e]("dragstop",i.stop)}
+var d=u.destroy
+return u.destroy=function(){d.apply(this,arguments),this.isEnabled=!1},h.Rect=i,h.Packer=n,h})
diff --git a/www/external/polyfill.min.js b/www/external/polyfill.min.js
new file mode 100644
index 00000000..dd753762
--- /dev/null
+++ b/www/external/polyfill.min.js
@@ -0,0 +1,4 @@
+!function(f){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=f();else if("function"==typeof define&&define.amd)define([],f);else{var g;g="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,g["default"]=f()}}(function(){return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var _require=require("./spec/reference-implementation/lib/readable-stream"),ReadableStream=_require.ReadableStream,_require2=require("./spec/reference-implementation/lib/writable-stream"),WritableStream=_require2.WritableStream,ByteLengthQueuingStrategy=require("./spec/reference-implementation/lib/byte-length-queuing-strategy"),CountQueuingStrategy=require("./spec/reference-implementation/lib/count-queuing-strategy"),TransformStream=require("./spec/reference-implementation/lib/transform-stream");exports.ByteLengthQueuingStrategy=ByteLengthQueuingStrategy,exports.CountQueuingStrategy=CountQueuingStrategy,exports.TransformStream=TransformStream,exports.ReadableStream=ReadableStream,exports.WritableStream=WritableStream;var interfaces={ReadableStream:ReadableStream,WritableStream:WritableStream,ByteLengthQueuingStrategy:ByteLengthQueuingStrategy,CountQueuingStrategy:CountQueuingStrategy,TransformStream:TransformStream};exports["default"]=interfaces,"undefined"!=typeof window&&Object.assign(window,interfaces)},{"./spec/reference-implementation/lib/byte-length-queuing-strategy":7,"./spec/reference-implementation/lib/count-queuing-strategy":8,"./spec/reference-implementation/lib/readable-stream":11,"./spec/reference-implementation/lib/transform-stream":12,"./spec/reference-implementation/lib/writable-stream":14}],2:[function(require,module,exports){function replacer(key,value){return util.isUndefined(value)?""+value:util.isNumber(value)&&!isFinite(value)?value.toString():util.isFunction(value)||util.isRegExp(value)?value.toString():value}function truncate(s,n){return util.isString(s)?s.length<n?s:s.slice(0,n):s}function getMessage(self){return truncate(JSON.stringify(self.actual,replacer),128)+" "+self.operator+" "+truncate(JSON.stringify(self.expected,replacer),128)}function fail(actual,expected,message,operator,stackStartFunction){throw new assert.AssertionError({message:message,actual:actual,expected:expected,operator:operator,stackStartFunction:stackStartFunction})}function ok(value,message){value||fail(value,!0,message,"==",assert.ok)}function _deepEqual(actual,expected){if(actual===expected)return!0;if(util.isBuffer(actual)&&util.isBuffer(expected)){if(actual.length!=expected.length)return!1;for(var i=0;i<actual.length;i++)if(actual[i]!==expected[i])return!1;return!0}return util.isDate(actual)&&util.isDate(expected)?actual.getTime()===expected.getTime():util.isRegExp(actual)&&util.isRegExp(expected)?actual.source===expected.source&&actual.global===expected.global&&actual.multiline===expected.multiline&&actual.lastIndex===expected.lastIndex&&actual.ignoreCase===expected.ignoreCase:util.isObject(actual)||util.isObject(expected)?objEquiv(actual,expected):actual==expected}function isArguments(object){return"[object Arguments]"==Object.prototype.toString.call(object)}function objEquiv(a,b){if(util.isNullOrUndefined(a)||util.isNullOrUndefined(b))return!1;if(a.prototype!==b.prototype)return!1;if(util.isPrimitive(a)||util.isPrimitive(b))return a===b;var aIsArgs=isArguments(a),bIsArgs=isArguments(b);if(aIsArgs&&!bIsArgs||!aIsArgs&&bIsArgs)return!1;if(aIsArgs)return a=pSlice.call(a),b=pSlice.call(b),_deepEqual(a,b);var key,i,ka=objectKeys(a),kb=objectKeys(b);if(ka.length!=kb.length)return!1;for(ka.sort(),kb.sort(),i=ka.length-1;i>=0;i--)if(ka[i]!=kb[i])return!1;for(i=ka.length-1;i>=0;i--)if(key=ka[i],!_deepEqual(a[key],b[key]))return!1;return!0}function expectedException(actual,expected){return actual&&expected?"[object RegExp]"==Object.prototype.toString.call(expected)?expected.test(actual):actual instanceof expected?!0:expected.call({},actual)===!0:!1}function _throws(shouldThrow,block,expected,message){var actual;util.isString(expected)&&(message=expected,expected=null);try{block()}catch(e){actual=e}if(message=(expected&&expected.name?" ("+expected.name+").":".")+(message?" "+message:"."),shouldThrow&&!actual&&fail(actual,expected,"Missing expected exception"+message),!shouldThrow&&expectedException(actual,expected)&&fail(actual,expected,"Got unwanted exception"+message),shouldThrow&&actual&&expected&&!expectedException(actual,expected)||!shouldThrow&&actual)throw actual}var util=require("util/"),pSlice=Array.prototype.slice,hasOwn=Object.prototype.hasOwnProperty,assert=module.exports=ok;assert.AssertionError=function(options){this.name="AssertionError",this.actual=options.actual,this.expected=options.expected,this.operator=options.operator,options.message?(this.message=options.message,this.generatedMessage=!1):(this.message=getMessage(this),this.generatedMessage=!0);var stackStartFunction=options.stackStartFunction||fail;if(Error.captureStackTrace)Error.captureStackTrace(this,stackStartFunction);else{var err=new Error;if(err.stack){var out=err.stack,fn_name=stackStartFunction.name,idx=out.indexOf("\n"+fn_name);if(idx>=0){var next_line=out.indexOf("\n",idx+1);out=out.substring(next_line+1)}this.stack=out}}},util.inherits(assert.AssertionError,Error),assert.fail=fail,assert.ok=ok,assert.equal=function(actual,expected,message){actual!=expected&&fail(actual,expected,message,"==",assert.equal)},assert.notEqual=function(actual,expected,message){actual==expected&&fail(actual,expected,message,"!=",assert.notEqual)},assert.deepEqual=function(actual,expected,message){_deepEqual(actual,expected)||fail(actual,expected,message,"deepEqual",assert.deepEqual)},assert.notDeepEqual=function(actual,expected,message){_deepEqual(actual,expected)&&fail(actual,expected,message,"notDeepEqual",assert.notDeepEqual)},assert.strictEqual=function(actual,expected,message){actual!==expected&&fail(actual,expected,message,"===",assert.strictEqual)},assert.notStrictEqual=function(actual,expected,message){actual===expected&&fail(actual,expected,message,"!==",assert.notStrictEqual)},assert["throws"]=function(block,error,message){_throws.apply(this,[!0].concat(pSlice.call(arguments)))},assert.doesNotThrow=function(block,message){_throws.apply(this,[!1].concat(pSlice.call(arguments)))},assert.ifError=function(err){if(err)throw err};var objectKeys=Object.keys||function(obj){var keys=[];for(var key in obj)hasOwn.call(obj,key)&&keys.push(key);return keys}},{"util/":6}],3:[function(require,module,exports){"function"==typeof Object.create?module.exports=function(ctor,superCtor){ctor.super_=superCtor,ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:!1,writable:!0,configurable:!0}})}:module.exports=function(ctor,superCtor){ctor.super_=superCtor;var TempCtor=function(){};TempCtor.prototype=superCtor.prototype,ctor.prototype=new TempCtor,ctor.prototype.constructor=ctor}},{}],4:[function(require,module,exports){function cleanUpNextTick(){draining&&currentQueue&&(draining=!1,currentQueue.length?queue=currentQueue.concat(queue):queueIndex=-1,queue.length&&drainQueue())}function drainQueue(){if(!draining){var timeout=cachedSetTimeout(cleanUpNextTick);draining=!0;for(var len=queue.length;len;){for(currentQueue=queue,queue=[];++queueIndex<len;)currentQueue&&currentQueue[queueIndex].run();queueIndex=-1,len=queue.length}currentQueue=null,draining=!1,cachedClearTimeout(timeout)}}function Item(fun,array){this.fun=fun,this.array=array}function noop(){}var cachedSetTimeout,cachedClearTimeout,process=module.exports={};!function(){try{cachedSetTimeout=setTimeout}catch(e){cachedSetTimeout=function(){throw new Error("setTimeout is not defined")}}try{cachedClearTimeout=clearTimeout}catch(e){cachedClearTimeout=function(){throw new Error("clearTimeout is not defined")}}}();var currentQueue,queue=[],draining=!1,queueIndex=-1;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)),1!==queue.length||draining||cachedSetTimeout(drainQueue,0)},Item.prototype.run=function(){this.fun.apply(null,this.array)},process.title="browser",process.browser=!0,process.env={},process.argv=[],process.version="",process.versions={},process.on=noop,process.addListener=noop,process.once=noop,process.off=noop,process.removeListener=noop,process.removeAllListeners=noop,process.emit=noop,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}},{}],5:[function(require,module,exports){module.exports=function(arg){return arg&&"object"==typeof arg&&"function"==typeof arg.copy&&"function"==typeof arg.fill&&"function"==typeof arg.readUInt8}},{}],6:[function(require,module,exports){(function(process,global){function inspect(obj,opts){var ctx={seen:[],stylize:stylizeNoColor};return arguments.length>=3&&(ctx.depth=arguments[2]),arguments.length>=4&&(ctx.colors=arguments[3]),isBoolean(opts)?ctx.showHidden=opts:opts&&exports._extend(ctx,opts),isUndefined(ctx.showHidden)&&(ctx.showHidden=!1),isUndefined(ctx.depth)&&(ctx.depth=2),isUndefined(ctx.colors)&&(ctx.colors=!1),isUndefined(ctx.customInspect)&&(ctx.customInspect=!0),ctx.colors&&(ctx.stylize=stylizeWithColor),formatValue(ctx,obj,ctx.depth)}function stylizeWithColor(str,styleType){var style=inspect.styles[styleType];return style?"["+inspect.colors[style][0]+"m"+str+"["+inspect.colors[style][1]+"m":str}function stylizeNoColor(str,styleType){return str}function arrayToHash(array){var hash={};return array.forEach(function(val,idx){hash[val]=!0}),hash}function formatValue(ctx,value,recurseTimes){if(ctx.customInspect&&value&&isFunction(value.inspect)&&value.inspect!==exports.inspect&&(!value.constructor||value.constructor.prototype!==value)){var ret=value.inspect(recurseTimes,ctx);return isString(ret)||(ret=formatValue(ctx,ret,recurseTimes)),ret}var primitive=formatPrimitive(ctx,value);if(primitive)return primitive;var keys=Object.keys(value),visibleKeys=arrayToHash(keys);if(ctx.showHidden&&(keys=Object.getOwnPropertyNames(value)),isError(value)&&(keys.indexOf("message")>=0||keys.indexOf("description")>=0))return formatError(value);if(0===keys.length){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=!1,braces=["{","}"];if(isArray(value)&&(array=!0,braces=["[","]"]),isFunction(value)){var n=value.name?": "+value.name:"";base=" [Function"+n+"]"}if(isRegExp(value)&&(base=" "+RegExp.prototype.toString.call(value)),isDate(value)&&(base=" "+Date.prototype.toUTCString.call(value)),isError(value)&&(base=" "+formatError(value)),0===keys.length&&(!array||0==value.length))return braces[0]+base+braces[1];if(0>recurseTimes)return isRegExp(value)?ctx.stylize(RegExp.prototype.toString.call(value),"regexp"):ctx.stylize("[Object]","special");ctx.seen.push(value);var output;return output=array?formatArray(ctx,value,recurseTimes,visibleKeys,keys):keys.map(function(key){return formatProperty(ctx,value,recurseTimes,visibleKeys,key,array)}),ctx.seen.pop(),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")}return isNumber(value)?ctx.stylize(""+value,"number"):isBoolean(value)?ctx.stylize(""+value,"boolean"):isNull(value)?ctx.stylize("null","null"):void 0}function formatError(value){return"["+Error.prototype.toString.call(value)+"]"}function formatArray(ctx,value,recurseTimes,visibleKeys,keys){for(var output=[],i=0,l=value.length;l>i;++i)hasOwnProperty(value,String(i))?output.push(formatProperty(ctx,value,recurseTimes,visibleKeys,String(i),!0)):output.push("");return keys.forEach(function(key){key.match(/^\d+$/)||output.push(formatProperty(ctx,value,recurseTimes,visibleKeys,key,!0))}),output}function formatProperty(ctx,value,recurseTimes,visibleKeys,key,array){var name,str,desc;if(desc=Object.getOwnPropertyDescriptor(value,key)||{value:value[key]},desc.get?str=desc.set?ctx.stylize("[Getter/Setter]","special"):ctx.stylize("[Getter]","special"):desc.set&&(str=ctx.stylize("[Setter]","special")),hasOwnProperty(visibleKeys,key)||(name="["+key+"]"),str||(ctx.seen.indexOf(desc.value)<0?(str=isNull(recurseTimes)?formatValue(ctx,desc.value,null):formatValue(ctx,desc.value,recurseTimes-1),str.indexOf("\n")>-1&&(str=array?str.split("\n").map(function(line){return" "+line}).join("\n").substr(2):"\n"+str.split("\n").map(function(line){return" "+line}).join("\n"))):str=ctx.stylize("[Circular]","special")),isUndefined(name)){if(array&&key.match(/^\d+$/))return str;name=JSON.stringify(""+key),name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(name=name.substr(1,name.length-2),name=ctx.stylize(name,"name")):(name=name.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),name=ctx.stylize(name,"string"))}return name+": "+str}function reduceToSingleString(output,base,braces){var numLinesEst=0,length=output.reduce(function(prev,cur){return numLinesEst++,cur.indexOf("\n")>=0&&numLinesEst++,prev+cur.replace(/\u001b\[\d\d?m/g,"").length+1},0);return length>60?braces[0]+(""===base?"":base+"\n ")+" "+output.join(",\n ")+" "+braces[1]:braces[0]+base+" "+output.join(", ")+" "+braces[1]}function isArray(ar){return Array.isArray(ar)}function isBoolean(arg){return"boolean"==typeof arg}function isNull(arg){return null===arg}function isNullOrUndefined(arg){return null==arg}function isNumber(arg){return"number"==typeof arg}function isString(arg){return"string"==typeof arg}function isSymbol(arg){return"symbol"==typeof arg}function isUndefined(arg){return void 0===arg}function isRegExp(re){return isObject(re)&&"[object RegExp]"===objectToString(re)}function isObject(arg){return"object"==typeof arg&&null!==arg}function isDate(d){return isObject(d)&&"[object Date]"===objectToString(d)}function isError(e){return isObject(e)&&("[object Error]"===objectToString(e)||e instanceof Error)}function isFunction(arg){return"function"==typeof arg}function isPrimitive(arg){return null===arg||"boolean"==typeof arg||"number"==typeof arg||"string"==typeof arg||"symbol"==typeof arg||"undefined"==typeof arg}function objectToString(o){return Object.prototype.toString.call(o)}function pad(n){return 10>n?"0"+n.toString(10):n.toString(10)}function timestamp(){var d=new Date,time=[pad(d.getHours()),pad(d.getMinutes()),pad(d.getSeconds())].join(":");return[d.getDate(),months[d.getMonth()],time].join(" ")}function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop)}var formatRegExp=/%[sdj%]/g;exports.format=function(f){if(!isString(f)){for(var objects=[],i=0;i<arguments.length;i++)objects.push(inspect(arguments[i]));return objects.join(" ")}for(var i=1,args=arguments,len=args.length,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}}),x=args[i];len>i;x=args[++i])str+=isNull(x)||!isObject(x)?" "+x:" "+inspect(x);return str},exports.deprecate=function(fn,msg){function deprecated(){if(!warned){if(process.throwDeprecation)throw new Error(msg);process.traceDeprecation?console.trace(msg):console.error(msg),warned=!0}return fn.apply(this,arguments)}if(isUndefined(global.process))return function(){return exports.deprecate(fn,msg).apply(this,arguments)};if(process.noDeprecation===!0)return fn;var warned=!1;return deprecated};var debugEnviron,debugs={};exports.debuglog=function(set){if(isUndefined(debugEnviron)&&(debugEnviron=process.env.NODE_DEBUG||""),set=set.toUpperCase(),!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]},exports.inspect=inspect,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]},inspect.styles={special:"cyan",number:"yellow","boolean":"yellow",undefined:"grey","null":"bold",string:"green",date:"magenta",regexp:"red"},exports.isArray=isArray,exports.isBoolean=isBoolean,exports.isNull=isNull,exports.isNullOrUndefined=isNullOrUndefined,exports.isNumber=isNumber,exports.isString=isString,exports.isSymbol=isSymbol,exports.isUndefined=isUndefined,exports.isRegExp=isRegExp,exports.isObject=isObject,exports.isDate=isDate,exports.isError=isError,exports.isFunction=isFunction,exports.isPrimitive=isPrimitive,exports.isBuffer=require("./support/isBuffer");var months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];exports.log=function(){console.log("%s - %s",timestamp(),exports.format.apply(exports,arguments))},exports.inherits=require("inherits"),exports._extend=function(origin,add){if(!add||!isObject(add))return origin;for(var keys=Object.keys(add),i=keys.length;i--;)origin[keys[i]]=add[keys[i]];return origin}}).call(this,require("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./support/isBuffer":5,_process:4,inherits:3}],7:[function(require,module,exports){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||!1,descriptor.configurable=!0,"value"in descriptor&&(descriptor.writable=!0),Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){return protoProps&&defineProperties(Constructor.prototype,protoProps),staticProps&&defineProperties(Constructor,staticProps),Constructor}}(),_require=require("./helpers.js"),createDataProperty=_require.createDataProperty;module.exports=function(){function ByteLengthQueuingStrategy(_ref){var highWaterMark=_ref.highWaterMark;_classCallCheck(this,ByteLengthQueuingStrategy),createDataProperty(this,"highWaterMark",highWaterMark)}return _createClass(ByteLengthQueuingStrategy,[{key:"size",value:function(chunk){return chunk.byteLength}}]),ByteLengthQueuingStrategy}()},{"./helpers.js":9}],8:[function(require,module,exports){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||!1,descriptor.configurable=!0,"value"in descriptor&&(descriptor.writable=!0),Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){return protoProps&&defineProperties(Constructor.prototype,protoProps),staticProps&&defineProperties(Constructor,staticProps),Constructor}}(),_require=require("./helpers.js"),createDataProperty=_require.createDataProperty;module.exports=function(){function CountQueuingStrategy(_ref){var highWaterMark=_ref.highWaterMark;_classCallCheck(this,CountQueuingStrategy),createDataProperty(this,"highWaterMark",highWaterMark)}return _createClass(CountQueuingStrategy,[{key:"size",value:function(){return 1}}]),CountQueuingStrategy}()},{"./helpers.js":9}],9:[function(require,module,exports){"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol?"symbol":typeof obj},assert=require("assert");exports.promiseCall=function(func){for(var _len=arguments.length,args=Array(_len>1?_len-1:0),_key=1;_len>_key;_key++)args[_key-1]=arguments[_key];try{return Promise.resolve(func.apply(void 0,args))}catch(e){return Promise.reject(e)}},exports.typeIsObject=function(x){return"object"===("undefined"==typeof x?"undefined":_typeof(x))&&null!==x||"function"==typeof x},exports.toInteger=function(v){return v=Number(v),isNaN(v)?0:0>v?-1*Math.floor(Math.abs(v)):Math.floor(Math.abs(v))},exports.createDataProperty=function(o,p,v){assert(exports.typeIsObject(o)),Object.defineProperty(o,p,{value:v,writable:!0,enumerable:!0,configurable:!0})},exports.createArrayFromList=function(elements){return elements.slice()},exports.ArrayBufferCopy=function(dest,destOffset,src,srcOffset,n){new Uint8Array(dest).set(new Uint8Array(src,srcOffset,n),destOffset)},exports.CreateIterResultObject=function(value,done){assert("boolean"==typeof done);var obj={};return Object.defineProperty(obj,"value",{value:value,enumerable:!0,writable:!0,configurable:!0}),Object.defineProperty(obj,"done",{value:done,enumerable:!0,writable:!0,configurable:!0}),obj},exports.IsFiniteNonNegativeNumber=function(v){return Number.isNaN(v)?!1:v===1/0?!1:!(0>v)},exports.InvokeOrNoop=function(O,P,args){var method=O[P];if(void 0!==method)return method.apply(O,args)},exports.PromiseInvokeOrNoop=function(O,P,args){var method=void 0;try{method=O[P]}catch(methodE){return Promise.reject(methodE)}if(void 0===method)return Promise.resolve(void 0);try{return Promise.resolve(method.apply(O,args))}catch(e){return Promise.reject(e)}},exports.PromiseInvokeOrFallbackOrNoop=function(O,P1,args1,P2,args2){var method=void 0;try{method=O[P1]}catch(methodE){return Promise.reject(methodE)}if(void 0===method)return exports.PromiseInvokeOrNoop(O,P2,args2);try{return Promise.resolve(method.apply(O,args1))}catch(e){return Promise.reject(e)}},exports.SameRealmTransfer=function(O){return O},exports.ValidateAndNormalizeHighWaterMark=function(highWaterMark){if(highWaterMark=Number(highWaterMark),Number.isNaN(highWaterMark)||0>highWaterMark)throw new RangeError("highWaterMark property of a queuing strategy must be nonnegative and non-NaN");return highWaterMark},exports.ValidateAndNormalizeQueuingStrategy=function(size,highWaterMark){if(void 0!==size&&"function"!=typeof size)throw new TypeError("size property of a queuing strategy must be a function");return highWaterMark=exports.ValidateAndNormalizeHighWaterMark(highWaterMark),{size:size,highWaterMark:highWaterMark}}},{assert:2}],10:[function(require,module,exports){"use strict";var assert=require("assert"),_require=require("./helpers.js"),IsFiniteNonNegativeNumber=_require.IsFiniteNonNegativeNumber;exports.DequeueValue=function(queue){assert(queue.length>0,"Spec-level failure: should never dequeue from an empty queue.");var pair=queue.shift();return queue._totalSize-=pair.size,pair.value},exports.EnqueueValueWithSize=function(queue,value,size){if(size=Number(size),!IsFiniteNonNegativeNumber(size))throw new RangeError("Size must be a finite, non-NaN, non-negative number.");queue.push({value:value,size:size}),void 0===queue._totalSize&&(queue._totalSize=0),queue._totalSize+=size},exports.GetTotalQueueSize=function(queue){return void 0===queue._totalSize&&(queue._totalSize=0),queue._totalSize},exports.PeekQueueValue=function(queue){assert(queue.length>0,"Spec-level failure: should never peek at an empty queue.");var pair=queue[0];return pair.value}},{"./helpers.js":9,assert:2}],11:[function(require,module,exports){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function AcquireReadableStreamBYOBReader(stream){return new ReadableStreamBYOBReader(stream)}function AcquireReadableStreamDefaultReader(stream){return new ReadableStreamDefaultReader(stream)}function IsReadableStream(x){return typeIsObject(x)?!!Object.prototype.hasOwnProperty.call(x,"_readableStreamController"):!1}function IsReadableStreamDisturbed(stream){return assert(IsReadableStream(stream)===!0,"IsReadableStreamDisturbed should only be used on known readable streams"),stream._disturbed}function IsReadableStreamLocked(stream){return assert(IsReadableStream(stream)===!0,"IsReadableStreamLocked should only be used on known readable streams"),void 0!==stream._reader}function ReadableStreamTee(stream,shouldClone){assert(IsReadableStream(stream)===!0),assert("boolean"==typeof shouldClone);var reader=AcquireReadableStreamDefaultReader(stream),teeState={closedOrErrored:!1,canceled1:!1,canceled2:!1,reason1:void 0,reason2:void 0};teeState.promise=new Promise(function(resolve){teeState._resolve=resolve});var pull=create_ReadableStreamTeePullFunction();pull._reader=reader,pull._teeState=teeState,pull._shouldClone=shouldClone;var cancel1=create_ReadableStreamTeeBranch1CancelFunction();cancel1._stream=stream,cancel1._teeState=teeState;var cancel2=create_ReadableStreamTeeBranch2CancelFunction();cancel2._stream=stream,cancel2._teeState=teeState;var underlyingSource1=Object.create(Object.prototype);createDataProperty(underlyingSource1,"pull",pull),createDataProperty(underlyingSource1,"cancel",cancel1);var branch1Stream=new ReadableStream(underlyingSource1),underlyingSource2=Object.create(Object.prototype);createDataProperty(underlyingSource2,"pull",pull),createDataProperty(underlyingSource2,"cancel",cancel2);var branch2Stream=new ReadableStream(underlyingSource2);return pull._branch1=branch1Stream._readableStreamController,pull._branch2=branch2Stream._readableStreamController,reader._closedPromise["catch"](function(r){teeState.closedOrErrored!==!0&&(ReadableStreamDefaultControllerError(pull._branch1,r),ReadableStreamDefaultControllerError(pull._branch2,r),teeState.closedOrErrored=!0)}),[branch1Stream,branch2Stream]}function create_ReadableStreamTeePullFunction(){function f(){var reader=f._reader,branch1=f._branch1,branch2=f._branch2,teeState=f._teeState;return ReadableStreamDefaultReaderRead(reader).then(function(result){assert(typeIsObject(result));var value=result.value,done=result.done;if(assert("boolean"==typeof done),done===!0&&teeState.closedOrErrored===!1&&(teeState.canceled1===!1&&ReadableStreamDefaultControllerClose(branch1),teeState.canceled2===!1&&ReadableStreamDefaultControllerClose(branch2),teeState.closedOrErrored=!0),teeState.closedOrErrored!==!0){if(teeState.canceled1===!1){var value1=value;ReadableStreamDefaultControllerEnqueue(branch1,value1)}if(teeState.canceled2===!1){var value2=value;ReadableStreamDefaultControllerEnqueue(branch2,value2)}}})}return f}function create_ReadableStreamTeeBranch1CancelFunction(){function f(reason){var stream=f._stream,teeState=f._teeState;if(teeState.canceled1=!0,teeState.reason1=reason,teeState.canceled2===!0){var compositeReason=createArrayFromList([teeState.reason1,teeState.reason2]),cancelResult=ReadableStreamCancel(stream,compositeReason);teeState._resolve(cancelResult)}return teeState.promise}return f}function create_ReadableStreamTeeBranch2CancelFunction(){function f(reason){var stream=f._stream,teeState=f._teeState;if(teeState.canceled2=!0,teeState.reason2=reason,teeState.canceled1===!0){var compositeReason=createArrayFromList([teeState.reason1,teeState.reason2]),cancelResult=ReadableStreamCancel(stream,compositeReason);teeState._resolve(cancelResult)}return teeState.promise}return f}function ReadableStreamAddReadIntoRequest(stream){assert(IsReadableStreamBYOBReader(stream._reader)===!0),assert("readable"===stream._state||"closed"===stream._state);var promise=new Promise(function(resolve,reject){var readIntoRequest={_resolve:resolve,_reject:reject};stream._reader._readIntoRequests.push(readIntoRequest)});return promise}function ReadableStreamAddReadRequest(stream){assert(IsReadableStreamDefaultReader(stream._reader)===!0),assert("readable"===stream._state);var promise=new Promise(function(resolve,reject){var readRequest={_resolve:resolve,_reject:reject};stream._reader._readRequests.push(readRequest)});return promise}function ReadableStreamCancel(stream,reason){if(stream._disturbed=!0,"closed"===stream._state)return Promise.resolve(void 0);if("errored"===stream._state)return Promise.reject(stream._storedError);ReadableStreamClose(stream);var sourceCancelPromise=stream._readableStreamController[InternalCancel](reason);return sourceCancelPromise.then(function(){})}function ReadableStreamClose(stream){assert("readable"===stream._state),stream._state="closed";var reader=stream._reader;if(void 0!==reader){if(IsReadableStreamDefaultReader(reader)===!0){var _iteratorNormalCompletion=!0,_didIteratorError=!1,_iteratorError=void 0;try{for(var _step,_iterator=reader._readRequests[Symbol.iterator]();!(_iteratorNormalCompletion=(_step=_iterator.next()).done);_iteratorNormalCompletion=!0){var _resolve=_step.value._resolve;_resolve(CreateIterResultObject(void 0,!0))}}catch(err){_didIteratorError=!0,_iteratorError=err}finally{try{!_iteratorNormalCompletion&&_iterator["return"]&&_iterator["return"]()}finally{if(_didIteratorError)throw _iteratorError}}reader._readRequests=[]}defaultReaderClosedPromiseResolve(reader)}}function ReadableStreamError(stream,e){assert(IsReadableStream(stream)===!0,"stream must be ReadableStream"),assert("readable"===stream._state,"state must be readable"),stream._state="errored",stream._storedError=e;var reader=stream._reader;if(void 0!==reader){if(IsReadableStreamDefaultReader(reader)===!0){var _iteratorNormalCompletion2=!0,_didIteratorError2=!1,_iteratorError2=void 0;try{for(var _step2,_iterator2=reader._readRequests[Symbol.iterator]();!(_iteratorNormalCompletion2=(_step2=_iterator2.next()).done);_iteratorNormalCompletion2=!0){var readRequest=_step2.value;readRequest._reject(e)}}catch(err){_didIteratorError2=!0,_iteratorError2=err}finally{try{!_iteratorNormalCompletion2&&_iterator2["return"]&&_iterator2["return"]()}finally{if(_didIteratorError2)throw _iteratorError2}}reader._readRequests=[]}else{assert(IsReadableStreamBYOBReader(reader),"reader must be ReadableStreamBYOBReader");var _iteratorNormalCompletion3=!0,_didIteratorError3=!1,_iteratorError3=void 0;try{for(var _step3,_iterator3=reader._readIntoRequests[Symbol.iterator]();!(_iteratorNormalCompletion3=(_step3=_iterator3.next()).done);_iteratorNormalCompletion3=!0){var readIntoRequest=_step3.value;readIntoRequest._reject(e)}}catch(err){_didIteratorError3=!0,_iteratorError3=err}finally{try{!_iteratorNormalCompletion3&&_iterator3["return"]&&_iterator3["return"]()}finally{if(_didIteratorError3)throw _iteratorError3}}reader._readIntoRequests=[]}defaultReaderClosedPromiseReject(reader,e)}}function ReadableStreamFulfillReadIntoRequest(stream,chunk,done){var reader=stream._reader;assert(reader._readIntoRequests.length>0);var readIntoRequest=reader._readIntoRequests.shift();readIntoRequest._resolve(CreateIterResultObject(chunk,done))}function ReadableStreamFulfillReadRequest(stream,chunk,done){var reader=stream._reader;assert(reader._readRequests.length>0);var readRequest=reader._readRequests.shift();readRequest._resolve(CreateIterResultObject(chunk,done))}function ReadableStreamGetNumReadIntoRequests(stream){return stream._reader._readIntoRequests.length}function ReadableStreamGetNumReadRequests(stream){
+return stream._reader._readRequests.length}function ReadableStreamHasBYOBReader(stream){var reader=stream._reader;return void 0===reader?!1:IsReadableStreamBYOBReader(reader)!==!1}function ReadableStreamHasDefaultReader(stream){var reader=stream._reader;return void 0===reader?!1:IsReadableStreamDefaultReader(reader)!==!1}function IsReadableStreamBYOBReader(x){return typeIsObject(x)?!!Object.prototype.hasOwnProperty.call(x,"_readIntoRequests"):!1}function IsReadableStreamDefaultReader(x){return typeIsObject(x)?!!Object.prototype.hasOwnProperty.call(x,"_readRequests"):!1}function ReadableStreamReaderGenericInitialize(reader,stream){reader._ownerReadableStream=stream,stream._reader=reader,"readable"===stream._state?defaultReaderClosedPromiseInitialize(reader):"closed"===stream._state?defaultReaderClosedPromiseInitializeAsResolved(reader):(assert("errored"===stream._state,"state must be errored"),defaultReaderClosedPromiseInitializeAsRejected(reader,stream._storedError))}function ReadableStreamReaderGenericCancel(reader,reason){var stream=reader._ownerReadableStream;return assert(void 0!==stream),ReadableStreamCancel(stream,reason)}function ReadableStreamReaderGenericRelease(reader){assert(void 0!==reader._ownerReadableStream),assert(reader._ownerReadableStream._reader===reader),"readable"===reader._ownerReadableStream._state?defaultReaderClosedPromiseReject(reader,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")):defaultReaderClosedPromiseResetToRejected(reader,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")),reader._ownerReadableStream._reader=void 0,reader._ownerReadableStream=void 0}function ReadableStreamBYOBReaderRead(reader,view){var stream=reader._ownerReadableStream;return assert(void 0!==stream),stream._disturbed=!0,"errored"===stream._state?Promise.reject(stream._storedError):ReadableByteStreamControllerPullInto(stream._readableStreamController,view)}function ReadableStreamDefaultReaderRead(reader){var stream=reader._ownerReadableStream;return assert(void 0!==stream),stream._disturbed=!0,"closed"===stream._state?Promise.resolve(CreateIterResultObject(void 0,!0)):"errored"===stream._state?Promise.reject(stream._storedError):(assert("readable"===stream._state),stream._readableStreamController[InternalPull]())}function IsReadableStreamDefaultController(x){return typeIsObject(x)?!!Object.prototype.hasOwnProperty.call(x,"_underlyingSource"):!1}function ReadableStreamDefaultControllerCallPullIfNeeded(controller){var shouldPull=ReadableStreamDefaultControllerShouldCallPull(controller);if(shouldPull!==!1){if(controller._pulling===!0)return void(controller._pullAgain=!0);controller._pulling=!0;var pullPromise=PromiseInvokeOrNoop(controller._underlyingSource,"pull",[controller]);pullPromise.then(function(){return controller._pulling=!1,controller._pullAgain===!0?(controller._pullAgain=!1,ReadableStreamDefaultControllerCallPullIfNeeded(controller)):void 0},function(e){ReadableStreamDefaultControllerErrorIfNeeded(controller,e)})["catch"](rethrowAssertionErrorRejection)}}function ReadableStreamDefaultControllerShouldCallPull(controller){var stream=controller._controlledReadableStream;if("closed"===stream._state||"errored"===stream._state)return!1;if(controller._closeRequested===!0)return!1;if(controller._started===!1)return!1;if(IsReadableStreamLocked(stream)===!0&&ReadableStreamGetNumReadRequests(stream)>0)return!0;var desiredSize=ReadableStreamDefaultControllerGetDesiredSize(controller);return desiredSize>0}function ReadableStreamDefaultControllerClose(controller){var stream=controller._controlledReadableStream;assert(controller._closeRequested===!1),assert("readable"===stream._state),controller._closeRequested=!0,0===controller._queue.length&&ReadableStreamClose(stream)}function ReadableStreamDefaultControllerEnqueue(controller,chunk){var stream=controller._controlledReadableStream;if(assert(controller._closeRequested===!1),assert("readable"===stream._state),IsReadableStreamLocked(stream)===!0&&ReadableStreamGetNumReadRequests(stream)>0)ReadableStreamFulfillReadRequest(stream,chunk,!1);else{var chunkSize=1;if(void 0!==controller._strategySize)try{chunkSize=controller._strategySize(chunk)}catch(chunkSizeE){throw ReadableStreamDefaultControllerErrorIfNeeded(controller,chunkSizeE),chunkSizeE}try{EnqueueValueWithSize(controller._queue,chunk,chunkSize)}catch(enqueueE){throw ReadableStreamDefaultControllerErrorIfNeeded(controller,enqueueE),enqueueE}}ReadableStreamDefaultControllerCallPullIfNeeded(controller)}function ReadableStreamDefaultControllerError(controller,e){var stream=controller._controlledReadableStream;assert("readable"===stream._state),controller._queue=[],ReadableStreamError(stream,e)}function ReadableStreamDefaultControllerErrorIfNeeded(controller,e){"readable"===controller._controlledReadableStream._state&&ReadableStreamDefaultControllerError(controller,e)}function ReadableStreamDefaultControllerGetDesiredSize(controller){var queueSize=GetTotalQueueSize(controller._queue);return controller._strategyHWM-queueSize}function IsReadableByteStreamController(x){return typeIsObject(x)?!!Object.prototype.hasOwnProperty.call(x,"_underlyingByteSource"):!1}function IsReadableStreamBYOBRequest(x){return typeIsObject(x)?!!Object.prototype.hasOwnProperty.call(x,"_associatedReadableByteStreamController"):!1}function ReadableByteStreamControllerCallPullIfNeeded(controller){var shouldPull=ReadableByteStreamControllerShouldCallPull(controller);if(shouldPull!==!1){if(controller._pulling===!0)return void(controller._pullAgain=!0);controller._pullAgain=!1,controller._pulling=!0;var pullPromise=PromiseInvokeOrNoop(controller._underlyingByteSource,"pull",[controller]);pullPromise.then(function(){controller._pulling=!1,controller._pullAgain===!0&&(controller._pullAgain=!1,ReadableByteStreamControllerCallPullIfNeeded(controller))},function(e){"readable"===controller._controlledReadableStream._state&&ReadableByteStreamControllerError(controller,e)})["catch"](rethrowAssertionErrorRejection)}}function ReadableByteStreamControllerClearPendingPullIntos(controller){ReadableByteStreamControllerInvalidateBYOBRequest(controller),controller._pendingPullIntos=[]}function ReadableByteStreamControllerCommitPullIntoDescriptor(stream,pullIntoDescriptor){assert("errored"!==stream._state,"state must not be errored");var done=!1;"closed"===stream._state&&(assert(0===pullIntoDescriptor.bytesFilled),done=!0);var filledView=ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);"default"===pullIntoDescriptor.readerType?ReadableStreamFulfillReadRequest(stream,filledView,done):(assert("byob"===pullIntoDescriptor.readerType),ReadableStreamFulfillReadIntoRequest(stream,filledView,done))}function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor){var bytesFilled=pullIntoDescriptor.bytesFilled,elementSize=pullIntoDescriptor.elementSize;return assert(bytesFilled<=pullIntoDescriptor.byteLength),assert(bytesFilled%elementSize===0),new pullIntoDescriptor.ctor(pullIntoDescriptor.buffer,pullIntoDescriptor.byteOffset,bytesFilled/elementSize)}function ReadableByteStreamControllerEnqueueChunkToQueue(controller,buffer,byteOffset,byteLength){controller._queue.push({buffer:buffer,byteOffset:byteOffset,byteLength:byteLength}),controller._totalQueuedBytes+=byteLength}function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller,pullIntoDescriptor){var elementSize=pullIntoDescriptor.elementSize,currentAlignedBytes=pullIntoDescriptor.bytesFilled-pullIntoDescriptor.bytesFilled%elementSize,maxBytesToCopy=Math.min(controller._totalQueuedBytes,pullIntoDescriptor.byteLength-pullIntoDescriptor.bytesFilled),maxBytesFilled=pullIntoDescriptor.bytesFilled+maxBytesToCopy,maxAlignedBytes=maxBytesFilled-maxBytesFilled%elementSize,totalBytesToCopyRemaining=maxBytesToCopy,ready=!1;maxAlignedBytes>currentAlignedBytes&&(totalBytesToCopyRemaining=maxAlignedBytes-pullIntoDescriptor.bytesFilled,ready=!0);for(var queue=controller._queue;totalBytesToCopyRemaining>0;){var headOfQueue=queue[0],bytesToCopy=Math.min(totalBytesToCopyRemaining,headOfQueue.byteLength),destStart=pullIntoDescriptor.byteOffset+pullIntoDescriptor.bytesFilled;ArrayBufferCopy(pullIntoDescriptor.buffer,destStart,headOfQueue.buffer,headOfQueue.byteOffset,bytesToCopy),headOfQueue.byteLength===bytesToCopy?queue.shift():(headOfQueue.byteOffset+=bytesToCopy,headOfQueue.byteLength-=bytesToCopy),controller._totalQueuedBytes-=bytesToCopy,ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller,bytesToCopy,pullIntoDescriptor),totalBytesToCopyRemaining-=bytesToCopy}return ready===!1&&(assert(0===controller._totalQueuedBytes,"queue must be empty"),assert(pullIntoDescriptor.bytesFilled>0),assert(pullIntoDescriptor.bytesFilled<pullIntoDescriptor.elementSize)),ready}function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller,size,pullIntoDescriptor){assert(0===controller._pendingPullIntos.length||controller._pendingPullIntos[0]===pullIntoDescriptor),ReadableByteStreamControllerInvalidateBYOBRequest(controller),pullIntoDescriptor.bytesFilled+=size}function ReadableByteStreamControllerHandleQueueDrain(controller){assert("readable"===controller._controlledReadableStream._state),0===controller._totalQueuedBytes&&controller._closeRequested===!0?ReadableStreamClose(controller._controlledReadableStream):ReadableByteStreamControllerCallPullIfNeeded(controller)}function ReadableByteStreamControllerInvalidateBYOBRequest(controller){void 0!==controller._byobRequest&&(controller._byobRequest._associatedReadableByteStreamController=void 0,controller._byobRequest._view=void 0,controller._byobRequest=void 0)}function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller){for(assert(controller._closeRequested===!1);controller._pendingPullIntos.length>0;){if(0===controller._totalQueuedBytes)return;var pullIntoDescriptor=controller._pendingPullIntos[0];ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller,pullIntoDescriptor)===!0&&(ReadableByteStreamControllerShiftPendingPullInto(controller),ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream,pullIntoDescriptor))}}function ReadableByteStreamControllerPullInto(controller,view){var stream=controller._controlledReadableStream,elementSize=1;view.constructor!==DataView&&(elementSize=view.constructor.BYTES_PER_ELEMENT);var ctor=view.constructor,pullIntoDescriptor={buffer:view.buffer,byteOffset:view.byteOffset,byteLength:view.byteLength,bytesFilled:0,elementSize:elementSize,ctor:ctor,readerType:"byob"};if(controller._pendingPullIntos.length>0)return pullIntoDescriptor.buffer=SameRealmTransfer(pullIntoDescriptor.buffer),controller._pendingPullIntos.push(pullIntoDescriptor),ReadableStreamAddReadIntoRequest(stream);if("closed"===stream._state){var emptyView=new view.constructor(view.buffer,view.byteOffset,0);return Promise.resolve(CreateIterResultObject(emptyView,!0))}if(controller._totalQueuedBytes>0){if(ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller,pullIntoDescriptor)===!0){var filledView=ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);return ReadableByteStreamControllerHandleQueueDrain(controller),Promise.resolve(CreateIterResultObject(filledView,!1))}if(controller._closeRequested===!0){var e=new TypeError("Insufficient bytes to fill elements in the given buffer");return ReadableByteStreamControllerError(controller,e),Promise.reject(e)}}pullIntoDescriptor.buffer=SameRealmTransfer(pullIntoDescriptor.buffer),controller._pendingPullIntos.push(pullIntoDescriptor);var promise=ReadableStreamAddReadIntoRequest(stream);return ReadableByteStreamControllerCallPullIfNeeded(controller),promise}function ReadableByteStreamControllerRespondInClosedState(controller,firstDescriptor){firstDescriptor.buffer=SameRealmTransfer(firstDescriptor.buffer),assert(0===firstDescriptor.bytesFilled,"bytesFilled must be 0");for(var stream=controller._controlledReadableStream;ReadableStreamGetNumReadIntoRequests(stream)>0;){var pullIntoDescriptor=ReadableByteStreamControllerShiftPendingPullInto(controller);ReadableByteStreamControllerCommitPullIntoDescriptor(stream,pullIntoDescriptor)}}function ReadableByteStreamControllerRespondInReadableState(controller,bytesWritten,pullIntoDescriptor){if(pullIntoDescriptor.bytesFilled+bytesWritten>pullIntoDescriptor.byteLength)throw new RangeError("bytesWritten out of range");if(ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller,bytesWritten,pullIntoDescriptor),!(pullIntoDescriptor.bytesFilled<pullIntoDescriptor.elementSize)){ReadableByteStreamControllerShiftPendingPullInto(controller);var remainderSize=pullIntoDescriptor.bytesFilled%pullIntoDescriptor.elementSize;if(remainderSize>0){var end=pullIntoDescriptor.byteOffset+pullIntoDescriptor.bytesFilled,remainder=pullIntoDescriptor.buffer.slice(end-remainderSize,end);ReadableByteStreamControllerEnqueueChunkToQueue(controller,remainder,0,remainder.byteLength)}pullIntoDescriptor.buffer=SameRealmTransfer(pullIntoDescriptor.buffer),pullIntoDescriptor.bytesFilled-=remainderSize,ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream,pullIntoDescriptor),ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller)}}function ReadableByteStreamControllerRespondInternal(controller,bytesWritten){var firstDescriptor=controller._pendingPullIntos[0],stream=controller._controlledReadableStream;if("closed"===stream._state){if(0!==bytesWritten)throw new TypeError("bytesWritten must be 0 when calling respond() on a closed stream");ReadableByteStreamControllerRespondInClosedState(controller,firstDescriptor)}else assert("readable"===stream._state),ReadableByteStreamControllerRespondInReadableState(controller,bytesWritten,firstDescriptor)}function ReadableByteStreamControllerShiftPendingPullInto(controller){var descriptor=controller._pendingPullIntos.shift();return ReadableByteStreamControllerInvalidateBYOBRequest(controller),descriptor}function ReadableByteStreamControllerShouldCallPull(controller){var stream=controller._controlledReadableStream;return"readable"!==stream._state?!1:controller._closeRequested===!0?!1:controller._started===!1?!1:ReadableStreamHasDefaultReader(stream)&&ReadableStreamGetNumReadRequests(stream)>0?!0:ReadableStreamHasBYOBReader(stream)&&ReadableStreamGetNumReadIntoRequests(stream)>0?!0:ReadableByteStreamControllerGetDesiredSize(controller)>0}function ReadableByteStreamControllerClose(controller){var stream=controller._controlledReadableStream;if(assert(controller._closeRequested===!1),assert("readable"===stream._state),controller._totalQueuedBytes>0)return void(controller._closeRequested=!0);if(controller._pendingPullIntos.length>0){var firstPendingPullInto=controller._pendingPullIntos[0];if(firstPendingPullInto.bytesFilled>0){var e=new TypeError("Insufficient bytes to fill elements in the given buffer");throw ReadableByteStreamControllerError(controller,e),e}}ReadableStreamClose(stream)}function ReadableByteStreamControllerEnqueue(controller,chunk){var stream=controller._controlledReadableStream;assert(controller._closeRequested===!1),assert("readable"===stream._state);var buffer=chunk.buffer,byteOffset=chunk.byteOffset,byteLength=chunk.byteLength,transferredBuffer=SameRealmTransfer(buffer);if(ReadableStreamHasDefaultReader(stream)===!0)if(0===ReadableStreamGetNumReadRequests(stream))ReadableByteStreamControllerEnqueueChunkToQueue(controller,transferredBuffer,byteOffset,byteLength);else{assert(0===controller._queue.length);var transferredView=new Uint8Array(transferredBuffer,byteOffset,byteLength);ReadableStreamFulfillReadRequest(stream,transferredView,!1)}else ReadableStreamHasBYOBReader(stream)===!0?(ReadableByteStreamControllerEnqueueChunkToQueue(controller,transferredBuffer,byteOffset,byteLength),ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller)):(assert(IsReadableStreamLocked(stream)===!1,"stream must not be locked"),ReadableByteStreamControllerEnqueueChunkToQueue(controller,transferredBuffer,byteOffset,byteLength))}function ReadableByteStreamControllerError(controller,e){var stream=controller._controlledReadableStream;assert("readable"===stream._state),ReadableByteStreamControllerClearPendingPullIntos(controller),controller._queue=[],ReadableStreamError(stream,e)}function ReadableByteStreamControllerGetDesiredSize(controller){return controller._strategyHWM-controller._totalQueuedBytes}function ReadableByteStreamControllerRespond(controller,bytesWritten){if(bytesWritten=Number(bytesWritten),IsFiniteNonNegativeNumber(bytesWritten)===!1)throw new RangeError("bytesWritten must be a finite");assert(controller._pendingPullIntos.length>0),ReadableByteStreamControllerRespondInternal(controller,bytesWritten)}function ReadableByteStreamControllerRespondWithNewView(controller,view){assert(controller._pendingPullIntos.length>0);var firstDescriptor=controller._pendingPullIntos[0];if(firstDescriptor.byteOffset+firstDescriptor.bytesFilled!==view.byteOffset)throw new RangeError("The region specified by view does not match byobRequest");if(firstDescriptor.byteLength!==view.byteLength)throw new RangeError("The buffer of view has different capacity than byobRequest");firstDescriptor.buffer=view.buffer,ReadableByteStreamControllerRespondInternal(controller,view.byteLength)}function streamBrandCheckException(name){return new TypeError("ReadableStream.prototype."+name+" can only be used on a ReadableStream")}function readerLockException(name){return new TypeError("Cannot "+name+" a stream using a released reader")}function defaultReaderBrandCheckException(name){return new TypeError("ReadableStreamDefaultReader.prototype."+name+" can only be used on a ReadableStreamDefaultReader")}function defaultReaderClosedPromiseInitialize(reader){reader._closedPromise=new Promise(function(resolve,reject){reader._closedPromise_resolve=resolve,reader._closedPromise_reject=reject})}function defaultReaderClosedPromiseInitializeAsRejected(reader,reason){reader._closedPromise=Promise.reject(reason),reader._closedPromise_resolve=void 0,reader._closedPromise_reject=void 0}function defaultReaderClosedPromiseInitializeAsResolved(reader){reader._closedPromise=Promise.resolve(void 0),reader._closedPromise_resolve=void 0,reader._closedPromise_reject=void 0}function defaultReaderClosedPromiseReject(reader,reason){assert(void 0!==reader._closedPromise_resolve),assert(void 0!==reader._closedPromise_reject),reader._closedPromise_reject(reason),reader._closedPromise_resolve=void 0,reader._closedPromise_reject=void 0}function defaultReaderClosedPromiseResetToRejected(reader,reason){assert(void 0===reader._closedPromise_resolve),assert(void 0===reader._closedPromise_reject),reader._closedPromise=Promise.reject(reason)}function defaultReaderClosedPromiseResolve(reader){assert(void 0!==reader._closedPromise_resolve),assert(void 0!==reader._closedPromise_reject),reader._closedPromise_resolve(void 0),reader._closedPromise_resolve=void 0,reader._closedPromise_reject=void 0}function byobReaderBrandCheckException(name){return new TypeError("ReadableStreamBYOBReader.prototype."+name+" can only be used on a ReadableStreamBYOBReader")}function defaultControllerBrandCheckException(name){return new TypeError("ReadableStreamDefaultController.prototype."+name+" can only be used on a ReadableStreamDefaultController")}function byobRequestBrandCheckException(name){return new TypeError("ReadableStreamBYOBRequest.prototype."+name+" can only be used on a ReadableStreamBYOBRequest")}function byteStreamControllerBrandCheckException(name){return new TypeError("ReadableByteStreamController.prototype."+name+" can only be used on a ReadableByteStreamController")}var _slicedToArray=function(){function sliceIterator(arr,i){var _arr=[],_n=!0,_d=!1,_e=void 0;try{for(var _s,_i=arr[Symbol.iterator]();!(_n=(_s=_i.next()).done)&&(_arr.push(_s.value),!i||_arr.length!==i);_n=!0);}catch(err){_d=!0,_e=err}finally{try{!_n&&_i["return"]&&_i["return"]()}finally{if(_d)throw _e}}return _arr}return function(arr,i){if(Array.isArray(arr))return arr;if(Symbol.iterator in Object(arr))return sliceIterator(arr,i);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),_createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||!1,descriptor.configurable=!0,"value"in descriptor&&(descriptor.writable=!0),Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){return protoProps&&defineProperties(Constructor.prototype,protoProps),staticProps&&defineProperties(Constructor,staticProps),Constructor}}(),assert=require("assert"),_require=require("./helpers.js"),ArrayBufferCopy=_require.ArrayBufferCopy,CreateIterResultObject=_require.CreateIterResultObject,IsFiniteNonNegativeNumber=_require.IsFiniteNonNegativeNumber,InvokeOrNoop=_require.InvokeOrNoop,PromiseInvokeOrNoop=_require.PromiseInvokeOrNoop,SameRealmTransfer=_require.SameRealmTransfer,ValidateAndNormalizeQueuingStrategy=_require.ValidateAndNormalizeQueuingStrategy,ValidateAndNormalizeHighWaterMark=_require.ValidateAndNormalizeHighWaterMark,_require2=require("./helpers.js"),createArrayFromList=_require2.createArrayFromList,createDataProperty=_require2.createDataProperty,typeIsObject=_require2.typeIsObject,_require3=require("./utils.js"),rethrowAssertionErrorRejection=_require3.rethrowAssertionErrorRejection,_require4=require("./queue-with-sizes.js"),DequeueValue=_require4.DequeueValue,EnqueueValueWithSize=_require4.EnqueueValueWithSize,GetTotalQueueSize=_require4.GetTotalQueueSize,InternalCancel=Symbol("[[Cancel]]"),InternalPull=Symbol("[[Pull]]"),ReadableStream=function(){function ReadableStream(){var underlyingSource=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],_ref=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],size=_ref.size,highWaterMark=_ref.highWaterMark;_classCallCheck(this,ReadableStream),this._state="readable",this._reader=void 0,this._storedError=void 0,this._disturbed=!1,this._readableStreamController=void 0;var type=underlyingSource.type,typeString=String(type);if("bytes"===typeString)void 0===highWaterMark&&(highWaterMark=0),this._readableStreamController=new ReadableByteStreamController(this,underlyingSource,highWaterMark);else{if(void 0!==type)throw new RangeError("Invalid type is specified");void 0===highWaterMark&&(highWaterMark=1),this._readableStreamController=new ReadableStreamDefaultController(this,underlyingSource,size,highWaterMark)}}return _createClass(ReadableStream,[{key:"cancel",value:function(reason){return IsReadableStream(this)===!1?Promise.reject(streamBrandCheckException("cancel")):IsReadableStreamLocked(this)===!0?Promise.reject(new TypeError("Cannot cancel a stream that already has a reader")):ReadableStreamCancel(this,reason)}},{key:"getReader",value:function(){var _ref2=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],mode=_ref2.mode;if(IsReadableStream(this)===!1)throw streamBrandCheckException("getReader");if("byob"===mode){if(IsReadableByteStreamController(this._readableStreamController)===!1)throw new TypeError("Cannot get a ReadableStreamBYOBReader for a stream not constructed with a byte source");return AcquireReadableStreamBYOBReader(this)}if(void 0===mode)return AcquireReadableStreamDefaultReader(this);throw new RangeError("Invalid mode is specified")}},{key:"pipeThrough",value:function(_ref3,options){var writable=_ref3.writable,readable=_ref3.readable;return this.pipeTo(writable,options),readable}},{key:"pipeTo",value:function(dest){function releaseReader(){_reader.releaseLock(),_reader=void 0}function releaseWriter(){_writer.releaseLock(),_writer=void 0}function pipeDone(){assert(void 0===_reader),assert(void 0===_writer),_state="done",_lastRead=void 0,_lastWrite=void 0,_allWrites=void 0}function finishWithFulfillment(){_resolvePipeToPromise(void 0),_resolvePipeToPromise=void 0,_rejectPipeToPromise=void 0,pipeDone()}function finishWithRejection(reason){_rejectPipeToPromise(reason),_resolvePipeToPromise=void 0,_rejectPipeToPromise=void 0,pipeDone()}function abortWriterCancelReader(reason,skipAbort,skipCancel){var promises=[];return skipAbort===!1?(_writer.abort(reason),releaseWriter()):void 0===_lastWrite?releaseWriter():promises.push(_lastWrite.then(function(){releaseWriter()},function(){releaseWriter()})),skipCancel===!1?(_reader.cancel(reason),releaseReader()):void 0===_lastRead?releaseReader():promises.push(_lastRead.then(function(){releaseReader()},function(){releaseReader()})),promises.length>0?(Promise.all(promises).then(function(){finishWithRejection(reason)}),void(_state="waitingForLastReadAndOrLastWrite")):void finishWithRejection(reason)}function handleWriteRejection(reason){"piping"===_state&&abortWriterCancelReader(reason,preventAbort,preventCancel)}function handleReadValue(value){_lastWrite=_writer.write(value),_lastWrite["catch"](handleWriteRejection),_allWrites=Promise.all([_allWrites,_lastWrite]),doPipe()}function handleReadDone(){return releaseReader(),preventClose===!1?(_writer.close().then(function(){return _allWrites},function(reason){releaseWriter(),finishWithRejection(reason)}).then(function(){releaseWriter(),finishWithFulfillment()}),void(_state="closingDest")):void 0===_lastWrite?(releaseWriter(),void finishWithFulfillment()):(_lastWrite.then(function(){releaseWriter(),finishWithFulfillment()},function(reason){releaseWriter(),finishWithRejection(reason)}),void(_state="waitingLastWriteOnReadableClosed"))}function doPipe(){_lastRead=_reader.read(),Promise.all([_lastRead,_writer.ready]).then(function(_ref5){var _ref6=_slicedToArray(_ref5,1),_ref6$=_ref6[0],value=_ref6$.value,done=_ref6$.done;"piping"===_state&&(Boolean(done)===!1?handleReadValue(value):handleReadDone())},function(){})["catch"](rethrowAssertionErrorRejection)}function handleReaderClosedRejection(reason){"piping"===_state&&(_lastRead=void 0,abortWriterCancelReader(reason,preventAbort,!0))}function handleUnexpectedWriterCloseAndError(reason){"piping"===_state&&(_lastWrite=void 0,abortWriterCancelReader(reason,!0,preventCancel))}function handleWriterClosedFulfillment(){handleUnexpectedWriterCloseAndError(new TypeError("dest closed unexpectedly"))}function handleWriterClosedRejection(reason){handleUnexpectedWriterCloseAndError(reason)}var _ref4=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],preventClose=_ref4.preventClose,preventAbort=_ref4.preventAbort,preventCancel=_ref4.preventCancel;preventClose=Boolean(preventClose),preventAbort=Boolean(preventAbort),preventCancel=Boolean(preventCancel);var source=this,_resolvePipeToPromise=void 0,_rejectPipeToPromise=void 0,_reader=void 0,_writer=void 0,_state="piping",_lastRead=void 0,_lastWrite=void 0,_allWrites=void 0;return new Promise(function(resolve,reject){_resolvePipeToPromise=resolve,_rejectPipeToPromise=reject,_reader=source.getReader(),_writer=dest.getWriter(),_reader.closed["catch"](handleReaderClosedRejection),_writer.closed.then(handleWriterClosedFulfillment,handleWriterClosedRejection),doPipe()})}},{key:"tee",value:function(){if(IsReadableStream(this)===!1)throw streamBrandCheckException("tee");var branches=ReadableStreamTee(this,!1);return createArrayFromList(branches)}},{key:"locked",get:function(){if(IsReadableStream(this)===!1)throw streamBrandCheckException("locked");return IsReadableStreamLocked(this)}}]),ReadableStream}();exports.ReadableStream=ReadableStream,exports.IsReadableStreamDisturbed=IsReadableStreamDisturbed;var ReadableStreamDefaultReader=function(){function ReadableStreamDefaultReader(stream){if(_classCallCheck(this,ReadableStreamDefaultReader),IsReadableStream(stream)===!1)throw new TypeError("ReadableStreamDefaultReader can only be constructed with a ReadableStream instance");if(IsReadableStreamLocked(stream)===!0)throw new TypeError("This stream has already been locked for exclusive reading by another reader");ReadableStreamReaderGenericInitialize(this,stream),this._readRequests=[]}return _createClass(ReadableStreamDefaultReader,[{key:"cancel",value:function(reason){return IsReadableStreamDefaultReader(this)===!1?Promise.reject(defaultReaderBrandCheckException("cancel")):void 0===this._ownerReadableStream?Promise.reject(readerLockException("cancel")):ReadableStreamReaderGenericCancel(this,reason)}},{key:"read",value:function(){return IsReadableStreamDefaultReader(this)===!1?Promise.reject(defaultReaderBrandCheckException("read")):void 0===this._ownerReadableStream?Promise.reject(readerLockException("read from")):ReadableStreamDefaultReaderRead(this)}},{key:"releaseLock",value:function(){if(IsReadableStreamDefaultReader(this)===!1)throw defaultReaderBrandCheckException("releaseLock");if(void 0!==this._ownerReadableStream){if(this._readRequests.length>0)throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");ReadableStreamReaderGenericRelease(this)}}},{key:"closed",get:function(){return IsReadableStreamDefaultReader(this)===!1?Promise.reject(defaultReaderBrandCheckException("closed")):this._closedPromise}}]),ReadableStreamDefaultReader}(),ReadableStreamBYOBReader=function(){function ReadableStreamBYOBReader(stream){if(_classCallCheck(this,ReadableStreamBYOBReader),!IsReadableStream(stream))throw new TypeError("ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a byte source");if(IsReadableStreamLocked(stream))throw new TypeError("This stream has already been locked for exclusive reading by another reader");ReadableStreamReaderGenericInitialize(this,stream),this._readIntoRequests=[]}return _createClass(ReadableStreamBYOBReader,[{key:"cancel",value:function(reason){return IsReadableStreamBYOBReader(this)?void 0===this._ownerReadableStream?Promise.reject(readerLockException("cancel")):ReadableStreamReaderGenericCancel(this,reason):Promise.reject(byobReaderBrandCheckException("cancel"))}},{key:"read",value:function(view){return IsReadableStreamBYOBReader(this)?void 0===this._ownerReadableStream?Promise.reject(readerLockException("read from")):ArrayBuffer.isView(view)?0===view.byteLength?Promise.reject(new TypeError("view must have non-zero byteLength")):ReadableStreamBYOBReaderRead(this,view):Promise.reject(new TypeError("view must be an array buffer view")):Promise.reject(byobReaderBrandCheckException("read"))}},{key:"releaseLock",value:function(){if(!IsReadableStreamBYOBReader(this))throw byobReaderBrandCheckException("releaseLock");if(void 0!==this._ownerReadableStream){if(this._readIntoRequests.length>0)throw new TypeError("Tried to release a reader lock when that reader has pending read() calls un-settled");ReadableStreamReaderGenericRelease(this)}}},{key:"closed",get:function(){return IsReadableStreamBYOBReader(this)?this._closedPromise:Promise.reject(byobReaderBrandCheckException("closed"))}}]),ReadableStreamBYOBReader}(),ReadableStreamDefaultController=function(){function ReadableStreamDefaultController(stream,underlyingSource,size,highWaterMark){if(_classCallCheck(this,ReadableStreamDefaultController),IsReadableStream(stream)===!1)throw new TypeError("ReadableStreamDefaultController can only be constructed with a ReadableStream instance");if(void 0!==stream._readableStreamController)throw new TypeError("ReadableStreamDefaultController instances can only be created by the ReadableStream constructor");this._controlledReadableStream=stream,this._underlyingSource=underlyingSource,this._queue=[],this._started=!1,this._closeRequested=!1,this._pullAgain=!1,this._pulling=!1;var normalizedStrategy=ValidateAndNormalizeQueuingStrategy(size,highWaterMark);this._strategySize=normalizedStrategy.size,this._strategyHWM=normalizedStrategy.highWaterMark;var controller=this,startResult=InvokeOrNoop(underlyingSource,"start",[this]);Promise.resolve(startResult).then(function(){controller._started=!0,
+ReadableStreamDefaultControllerCallPullIfNeeded(controller)},function(r){ReadableStreamDefaultControllerErrorIfNeeded(controller,r)})["catch"](rethrowAssertionErrorRejection)}return _createClass(ReadableStreamDefaultController,[{key:"close",value:function(){if(IsReadableStreamDefaultController(this)===!1)throw defaultControllerBrandCheckException("close");if(this._closeRequested===!0)throw new TypeError("The stream has already been closed; do not close it again!");var state=this._controlledReadableStream._state;if("readable"!==state)throw new TypeError("The stream (in "+state+" state) is not in the readable state and cannot be closed");ReadableStreamDefaultControllerClose(this)}},{key:"enqueue",value:function(chunk){if(IsReadableStreamDefaultController(this)===!1)throw defaultControllerBrandCheckException("enqueue");if(this._closeRequested===!0)throw new TypeError("stream is closed or draining");var state=this._controlledReadableStream._state;if("readable"!==state)throw new TypeError("The stream (in "+state+" state) is not in the readable state and cannot be enqueued to");return ReadableStreamDefaultControllerEnqueue(this,chunk)}},{key:"error",value:function(e){if(IsReadableStreamDefaultController(this)===!1)throw defaultControllerBrandCheckException("error");var stream=this._controlledReadableStream;if("readable"!==stream._state)throw new TypeError("The stream is "+stream._state+" and so cannot be errored");ReadableStreamDefaultControllerError(this,e)}},{key:InternalCancel,value:function(reason){return this._queue=[],PromiseInvokeOrNoop(this._underlyingSource,"cancel",[reason])}},{key:InternalPull,value:function(){var stream=this._controlledReadableStream;if(this._queue.length>0){var chunk=DequeueValue(this._queue);return this._closeRequested===!0&&0===this._queue.length?ReadableStreamClose(stream):ReadableStreamDefaultControllerCallPullIfNeeded(this),Promise.resolve(CreateIterResultObject(chunk,!1))}var pendingPromise=ReadableStreamAddReadRequest(stream);return ReadableStreamDefaultControllerCallPullIfNeeded(this),pendingPromise}},{key:"desiredSize",get:function(){if(IsReadableStreamDefaultController(this)===!1)throw defaultControllerBrandCheckException("desiredSize");return ReadableStreamDefaultControllerGetDesiredSize(this)}}]),ReadableStreamDefaultController}(),ReadableStreamBYOBRequest=function(){function ReadableStreamBYOBRequest(controller,view){_classCallCheck(this,ReadableStreamBYOBRequest),this._associatedReadableByteStreamController=controller,this._view=view}return _createClass(ReadableStreamBYOBRequest,[{key:"respond",value:function(bytesWritten){if(IsReadableStreamBYOBRequest(this)===!1)throw byobRequestBrandCheckException("respond");if(void 0===this._associatedReadableByteStreamController)throw new TypeError("This BYOB request has been invalidated");ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController,bytesWritten)}},{key:"respondWithNewView",value:function(view){if(IsReadableStreamBYOBRequest(this)===!1)throw byobRequestBrandCheckException("respond");if(void 0===this._associatedReadableByteStreamController)throw new TypeError("This BYOB request has been invalidated");if(!ArrayBuffer.isView(view))throw new TypeError("You can only respond with array buffer views");ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController,view)}},{key:"view",get:function(){return this._view}}]),ReadableStreamBYOBRequest}(),ReadableByteStreamController=function(){function ReadableByteStreamController(stream,underlyingByteSource,highWaterMark){if(_classCallCheck(this,ReadableByteStreamController),IsReadableStream(stream)===!1)throw new TypeError("ReadableByteStreamController can only be constructed with a ReadableStream instance given a byte source");if(void 0!==stream._readableStreamController)throw new TypeError("ReadableByteStreamController instances can only be created by the ReadableStream constructor given a byte source");this._controlledReadableStream=stream,this._underlyingByteSource=underlyingByteSource,this._pullAgain=!1,this._pulling=!1,ReadableByteStreamControllerClearPendingPullIntos(this),this._queue=[],this._totalQueuedBytes=0,this._closeRequested=!1,this._started=!1,this._strategyHWM=ValidateAndNormalizeHighWaterMark(highWaterMark);var autoAllocateChunkSize=underlyingByteSource.autoAllocateChunkSize;if(void 0!==autoAllocateChunkSize&&(Number.isInteger(autoAllocateChunkSize)===!1||0>autoAllocateChunkSize))throw new RangeError("autoAllocateChunkSize must be a non negative integer");this._autoAllocateChunkSize=autoAllocateChunkSize,this._pendingPullIntos=[];var controller=this,startResult=InvokeOrNoop(underlyingByteSource,"start",[this]);Promise.resolve(startResult).then(function(){controller._started=!0,assert(controller._pulling===!1),assert(controller._pullAgain===!1),ReadableByteStreamControllerCallPullIfNeeded(controller)},function(r){"readable"===stream._state&&ReadableByteStreamControllerError(controller,r)})["catch"](rethrowAssertionErrorRejection)}return _createClass(ReadableByteStreamController,[{key:"close",value:function(){if(IsReadableByteStreamController(this)===!1)throw byteStreamControllerBrandCheckException("close");if(this._closeRequested===!0)throw new TypeError("The stream has already been closed; do not close it again!");var state=this._controlledReadableStream._state;if("readable"!==state)throw new TypeError("The stream (in "+state+" state) is not in the readable state and cannot be closed");ReadableByteStreamControllerClose(this)}},{key:"enqueue",value:function(chunk){if(IsReadableByteStreamController(this)===!1)throw byteStreamControllerBrandCheckException("enqueue");if(this._closeRequested===!0)throw new TypeError("stream is closed or draining");var state=this._controlledReadableStream._state;if("readable"!==state)throw new TypeError("The stream (in "+state+" state) is not in the readable state and cannot be enqueued to");if(!ArrayBuffer.isView(chunk))throw new TypeError("You can only enqueue array buffer views when using a ReadableByteStreamController");ReadableByteStreamControllerEnqueue(this,chunk)}},{key:"error",value:function(e){if(IsReadableByteStreamController(this)===!1)throw byteStreamControllerBrandCheckException("error");var stream=this._controlledReadableStream;if("readable"!==stream._state)throw new TypeError("The stream is "+stream._state+" and so cannot be errored");ReadableByteStreamControllerError(this,e)}},{key:InternalCancel,value:function(reason){if(this._pendingPullIntos.length>0){var firstDescriptor=this._pendingPullIntos[0];firstDescriptor.bytesFilled=0}return this._queue=[],this._totalQueuedBytes=0,PromiseInvokeOrNoop(this._underlyingByteSource,"cancel",[reason])}},{key:InternalPull,value:function(){var stream=this._controlledReadableStream;if(0===ReadableStreamGetNumReadRequests(stream)){if(this._totalQueuedBytes>0){var entry=this._queue.shift();this._totalQueuedBytes-=entry.byteLength,ReadableByteStreamControllerHandleQueueDrain(this);var view=void 0;try{view=new Uint8Array(entry.buffer,entry.byteOffset,entry.byteLength)}catch(viewE){return Promise.reject(viewE)}return Promise.resolve(CreateIterResultObject(view,!1))}var autoAllocateChunkSize=this._autoAllocateChunkSize;if(void 0!==autoAllocateChunkSize){var buffer=void 0;try{buffer=new ArrayBuffer(autoAllocateChunkSize)}catch(bufferE){return Promise.reject(bufferE)}var pullIntoDescriptor={buffer:buffer,byteOffset:0,byteLength:autoAllocateChunkSize,bytesFilled:0,elementSize:1,ctor:Uint8Array,readerType:"default"};this._pendingPullIntos.push(pullIntoDescriptor)}}else assert(void 0===this._autoAllocateChunkSize);var promise=ReadableStreamAddReadRequest(stream);return ReadableByteStreamControllerCallPullIfNeeded(this),promise}},{key:"byobRequest",get:function(){if(IsReadableByteStreamController(this)===!1)throw byteStreamControllerBrandCheckException("byobRequest");if(void 0===this._byobRequest&&this._pendingPullIntos.length>0){var firstDescriptor=this._pendingPullIntos[0],view=new Uint8Array(firstDescriptor.buffer,firstDescriptor.byteOffset+firstDescriptor.bytesFilled,firstDescriptor.byteLength-firstDescriptor.bytesFilled);this._byobRequest=new ReadableStreamBYOBRequest(this,view)}return this._byobRequest}},{key:"desiredSize",get:function(){if(IsReadableByteStreamController(this)===!1)throw byteStreamControllerBrandCheckException("desiredSize");return ReadableByteStreamControllerGetDesiredSize(this)}}]),ReadableByteStreamController}()},{"./helpers.js":9,"./queue-with-sizes.js":10,"./utils.js":13,assert:2}],12:[function(require,module,exports){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function TransformStreamCloseReadable(transformStream){if(transformStream._errored===!0)throw new TypeError("TransformStream is already errored");if(transformStream._readableClosed===!0)throw new TypeError("Readable side is already closed");try{transformStream._readableController.close()}catch(e){assert(!1)}transformStream._readableClosed=!0}function TransformStreamEnqueueToReadable(transformStream,chunk){if(transformStream._errroed===!0)throw new TypeError("TransformStream is already errored");if(transformStream._readableClosed===!0)throw new TypeError("Readable side is already closed");var controller=transformStream._readableController;transformStream._readableBackpressure=!0;try{controller.enqueue(chunk)}catch(e){if(transformStream._error===!1){var reason=new TypeError("Failed to enqueue to readable side");TransformStreamErrorInternal(transformStream,reason)}throw transformStream._error}var backpressure=void 0;try{backpressure=controller.desiredSize<=0}catch(e){if(transformStream._error===!1){var reason=new TypeError("Failed to calculate backpressure of readable side");TransformStreamError(transformStream,reason)}throw transformStream._error}backpressure&&(transformStream._readableBackpressure=!1)}function TransformStreamError(transformStream,e){if(transformStream._errored===!0)throw new TypeError("TransformStream is already errored");TransformStreamErrorInternal(transformStream,e)}function TransformStreamChunkDone(transformStream){if(transformStream._errroed===!0)throw new TypeError("TransformStream is already errored");if(transformStream._transforming===!1)throw new TypeError("No active transform is running");assert(void 0!==transformStream._resolveWrite),transformStream._transforming=!1,transformStream._resolveWrite(void 0),transformStream._resolveWrite=void 0,TransformStreamTransformIfNeeded(transformStream)}function TransformStreamErrorInternal(transformStream,e){transformStream._errored=!0,transformStream._writableDone===!1&&transformStream._writableController.error(e),transformStream._readableClosed===!1&&transformStream._readableController.error(e),transformStream._chunk=void 0,void 0!==transformStream._resolveWriter&&transformStream._resolveWriter(void 0)}function TransformStreamTransformIfNeeded(transformStream){if(transformStream._chunkPending!==!1&&(assert(void 0!==transformStream._resolveWrite),transformStream._transforming!==!0&&transformStream._readableBackpressure!==!0)){transformStream._transforming=!0;var chunk=transformStream._chunk;transformStream._chunkPending=!1,transformStream._chunk=void 0;try{void 0!==transformStream._transformer.transform&&transformStream._transformer.transform(chunk,TransformStreamChunkDone.bind(void 0,transformStream),transformStream._enqueueFunction,transformStream._closeFunction,transformStream._errorFunction)}catch(e){transformStream._errored===!1&&TransformStreamErrorInternal(transformStream,e)}}}function TransformStreamStart(transformStream){void 0!==transformStream._transformer.start&&transformStream._transformer.start(transformStream._enqueueFunction,transformStream._closeFunction,transformStream._errorFunction)}var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||!1,descriptor.configurable=!0,"value"in descriptor&&(descriptor.writable=!0),Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){return protoProps&&defineProperties(Constructor.prototype,protoProps),staticProps&&defineProperties(Constructor,staticProps),Constructor}}(),assert=require("assert"),_require=require("./readable-stream.js"),ReadableStream=_require.ReadableStream,_require2=require("./writable-stream.js"),WritableStream=_require2.WritableStream,TransformStreamSink=function(){function TransformStreamSink(transformStream){_classCallCheck(this,TransformStreamSink),this._transformStream=transformStream}return _createClass(TransformStreamSink,[{key:"start",value:function(c){var transformStream=this._transformStream;transformStream._writableController=c,void 0!==transformStream._readableController&&TransformStreamStart(transformStream)}},{key:"write",value:function(chunk){var transformStream=this._transformStream;assert(transformStream._errored===!1),assert(transformStream._chunkPending===!1),assert(void 0===transformStream._chunk),assert(void 0===transformStream._resolveWrite),transformStream._chunkPending=!0,transformStream._chunk=chunk;var promise=new Promise(function(resolve){transformStream._resolveWrite=resolve});return TransformStreamTransformIfNeeded(transformStream),promise}},{key:"abort",value:function(){var transformStream=this._transformStream;transformStream._writableDone=!0,TransformStreamErrorInternal(transformStream,new TypeError("Writable side aborted"))}},{key:"close",value:function(){var transformStream=this._transformStream;if(assert(transformStream._chunkPending===!1),assert(void 0===transformStream._chunk),assert(void 0===transformStream._resolveWrite),assert(transformStream._transforming===!1),transformStream._writableDone=!0,void 0===transformStream._transformer.flush)TransformStreamCloseReadable(transformStream);else try{transformStream._transformer.flush(transformStream._enqueueFunction,transformStream._closeFunction,transformStream._errorFunction)}catch(e){if(transformStream._errored===!1)throw TransformStreamErrorInternal(transformStream,e),e}}}]),TransformStreamSink}(),TransformStreamSource=function(){function TransformStreamSource(transformStream){_classCallCheck(this,TransformStreamSource),this._transformStream=transformStream}return _createClass(TransformStreamSource,[{key:"start",value:function(c){var transformStream=this._transformStream;transformStream._readableController=c,void 0!==transformStream._writableController&&TransformStreamStart(transformStream)}},{key:"pull",value:function(){this._transformStream._readableBackpressure=!1,TransformStreamTransformIfNeeded(this._transformStream)}},{key:"cancel",value:function(){var transformStream=this._transformStream;transformStream._readableClosed=!0,TransformStreamErrorInternal(transformStream,new TypeError("Readable side canceled"))}}]),TransformStreamSource}();module.exports=function TransformStream(transformer){if(_classCallCheck(this,TransformStream),void 0!==transformer.start&&"function"!=typeof transformer.start)throw new TypeError("start must be a function or undefined");if("function"!=typeof transformer.transform)throw new TypeError("transform must be a function");if(void 0!==transformer.flush&&"function"!=typeof transformer.flush)throw new TypeError("flush must be a function or undefined");this._transformer=transformer,this._transforming=!1,this._errored=!1,this._writableController=void 0,this._readableController=void 0,this._writableDone=!1,this._readableClosed=!1,this._resolveWrite=void 0,this._chunkPending=!1,this._chunk=void 0,this._enqueueFunction=TransformStreamEnqueueToReadable.bind(void 0,this),this._closeFunction=TransformStreamCloseReadable.bind(void 0,this),this._errorFunction=TransformStreamError.bind(void 0,this);var sink=new TransformStreamSink(this);try{this.writable=new WritableStream(sink,transformer.writableStrategy)}catch(e){if(this._errored===!1)throw TransformStreamError(this,e),e;return}var source=new TransformStreamSource(this);try{this.readable=new ReadableStream(source,transformer.readableStrategy)}catch(e){if(this.writable=void 0,this._errored===!1)throw TransformStreamError(this,e),e}}},{"./readable-stream.js":11,"./writable-stream.js":14,assert:2}],13:[function(require,module,exports){"use strict";var assert=require("assert");exports.rethrowAssertionErrorRejection=function(e){e&&e.constructor===assert.AssertionError&&setTimeout(function(){throw e},0)}},{assert:2}],14:[function(require,module,exports){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function AcquireWritableStreamDefaultWriter(stream){return new WritableStreamDefaultWriter(stream)}function IsWritableStream(x){return typeIsObject(x)?!!Object.prototype.hasOwnProperty.call(x,"_writableStreamController"):!1}function IsWritableStreamLocked(stream){return assert(IsWritableStream(stream)===!0,"IsWritableStreamLocked should only be used on known writable streams"),void 0!==stream._writer}function WritableStreamAbort(stream,reason){var state=stream._state;if("closed"===state)return Promise.resolve(void 0);if("errored"===state)return Promise.reject(stream._storedError);assert("writable"===state||"closing"===state);var error=new TypeError("Aborted");return WritableStreamError(stream,error),WritableStreamDefaultControllerAbort(stream._writableStreamController,reason)}function WritableStreamAddWriteRequest(stream){assert(IsWritableStreamLocked(stream)===!0),assert("writable"===stream._state);var promise=new Promise(function(resolve,reject){var writeRequest={_resolve:resolve,_reject:reject};stream._writeRequests.push(writeRequest)});return promise}function WritableStreamError(stream,e){var state=stream._state;assert("writable"===state||"closing"===state);var _iteratorNormalCompletion=!0,_didIteratorError=!1,_iteratorError=void 0;try{for(var _step,_iterator=stream._writeRequests[Symbol.iterator]();!(_iteratorNormalCompletion=(_step=_iterator.next()).done);_iteratorNormalCompletion=!0){var writeRequest=_step.value;writeRequest._reject(e)}}catch(err){_didIteratorError=!0,_iteratorError=err}finally{try{!_iteratorNormalCompletion&&_iterator["return"]&&_iterator["return"]()}finally{if(_didIteratorError)throw _iteratorError}}stream._writeRequests=[];var writer=stream._writer;void 0!==writer&&(defaultWriterClosedPromiseReject(writer,e),"writable"===state&&WritableStreamDefaultControllerGetBackpressure(stream._writableStreamController)===!0&&defaultWriterReadyPromiseResolve(writer)),stream._state="errored",stream._storedError=e}function WritableStreamFinishClose(stream){assert("closing"===stream._state),assert(void 0!==stream._writer),stream._state="closed",defaultWriterClosedPromiseResolve(stream._writer)}function WritableStreamFulfillWriteRequest(stream){assert(stream._writeRequests.length>0);var writeRequest=stream._writeRequests.shift();writeRequest._resolve(void 0)}function WritableStreamUpdateBackpressure(stream,backpressure){assert("writable"===stream._state);var writer=stream._writer;void 0!==writer&&(backpressure===!0?defaultWriterReadyPromiseReset(writer):(assert(backpressure===!1),defaultWriterReadyPromiseResolve(writer)))}function IsWritableStreamDefaultWriter(x){return typeIsObject(x)?!!Object.prototype.hasOwnProperty.call(x,"_ownerWritableStream"):!1}function WritableStreamDefaultWriterAbort(writer,reason){var stream=writer._ownerWritableStream;return assert(void 0!==stream),WritableStreamAbort(stream,reason)}function WritableStreamDefaultWriterClose(writer){var stream=writer._ownerWritableStream;assert(void 0!==stream);var state=stream._state;if("closed"===state||"errored"===state)return Promise.reject(new TypeError("The stream (in "+state+" state) is not in the writable state and cannot be closed"));assert("writable"===state);var promise=WritableStreamAddWriteRequest(stream);return WritableStreamDefaultControllerGetBackpressure(stream._writableStreamController)===!0&&defaultWriterReadyPromiseResolve(writer),stream._state="closing",WritableStreamDefaultControllerClose(stream._writableStreamController),promise}function WritableStreamDefaultWriterGetDesiredSize(writer){var stream=writer._ownerWritableStream,state=stream._state;return"errored"===state?null:"closed"===state?0:WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController)}function WritableStreamDefaultWriterWrite(writer,chunk){var stream=writer._ownerWritableStream;assert(void 0!==stream);var state=stream._state;if("closed"===state||"errored"===state)return Promise.reject(new TypeError("The stream (in "+state+" state) is not in the writable state and cannot be written to"));assert("writable"===state);var promise=WritableStreamAddWriteRequest(stream);return WritableStreamDefaultControllerWrite(stream._writableStreamController,chunk),promise}function WritableStreamDefaultControllerAbort(controller,reason){controller._queue=[];var sinkAbortPromise=PromiseInvokeOrFallbackOrNoop(controller._underlyingSink,"abort",[reason],"close",[]);return sinkAbortPromise.then(function(){})}function WritableStreamDefaultControllerClose(controller){EnqueueValueWithSize(controller._queue,"close",0),WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller)}function WritableStreamDefaultControllerGetDesiredSize(controller){var queueSize=GetTotalQueueSize(controller._queue);return controller._strategyHWM-queueSize}function WritableStreamDefaultControllerWrite(controller,chunk){var stream=controller._controlledWritableStream;assert("writable"===stream._state);var chunkSize=1;if(void 0!==controller._strategySize)try{chunkSize=controller._strategySize(chunk)}catch(chunkSizeE){return WritableStreamDefaultControllerErrorIfNeeded(controller,chunkSizeE),Promise.reject(chunkSizeE)}var writeRecord={chunk:chunk},lastBackpressure=WritableStreamDefaultControllerGetBackpressure(controller);try{EnqueueValueWithSize(controller._queue,writeRecord,chunkSize)}catch(enqueueE){return WritableStreamDefaultControllerErrorIfNeeded(controller,enqueueE),Promise.reject(enqueueE)}if("writable"===stream._state){var backpressure=WritableStreamDefaultControllerGetBackpressure(controller);lastBackpressure!==backpressure&&WritableStreamUpdateBackpressure(stream,backpressure)}WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller)}function IsWritableStreamDefaultController(x){return typeIsObject(x)?!!Object.prototype.hasOwnProperty.call(x,"_underlyingSink"):!1}function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller){if("closed"!==controller._controlledWritableStream._state&&"errored"!==controller._controlledWritableStream._state&&controller._started!==!1&&controller._writing!==!0&&0!==controller._queue.length){var writeRecord=PeekQueueValue(controller._queue);"close"===writeRecord?WritableStreamDefaultControllerProcessClose(controller):WritableStreamDefaultControllerProcessWrite(controller,writeRecord.chunk)}}function WritableStreamDefaultControllerErrorIfNeeded(controller,e){"writable"!==controller._controlledWritableStream._state&&"closing"!==controller._controlledWritableStream._state||WritableStreamDefaultControllerError(controller,e)}function WritableStreamDefaultControllerProcessClose(controller){var stream=controller._controlledWritableStream;assert("closing"===stream._state,"can't process final write record unless already closed"),DequeueValue(controller._queue),assert(0===controller._queue.length,"queue must be empty once the final write record is dequeued");var sinkClosePromise=PromiseInvokeOrNoop(controller._underlyingSink,"close");sinkClosePromise.then(function(){"closing"===stream._state&&(WritableStreamFulfillWriteRequest(stream),WritableStreamFinishClose(stream))},function(r){WritableStreamDefaultControllerErrorIfNeeded(controller,r)})["catch"](rethrowAssertionErrorRejection)}function WritableStreamDefaultControllerProcessWrite(controller,chunk){controller._writing=!0;var sinkWritePromise=PromiseInvokeOrNoop(controller._underlyingSink,"write",[chunk]);sinkWritePromise.then(function(){var stream=controller._controlledWritableStream,state=stream._state;if("errored"!==state&&"closed"!==state){controller._writing=!1,WritableStreamFulfillWriteRequest(stream);var lastBackpressure=WritableStreamDefaultControllerGetBackpressure(controller);if(DequeueValue(controller._queue),"closing"!==state){var backpressure=WritableStreamDefaultControllerGetBackpressure(controller);lastBackpressure!==backpressure&&WritableStreamUpdateBackpressure(controller._controlledWritableStream,backpressure)}WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller)}},function(r){WritableStreamDefaultControllerErrorIfNeeded(controller,r)})["catch"](rethrowAssertionErrorRejection)}function WritableStreamDefaultControllerGetBackpressure(controller){var desiredSize=WritableStreamDefaultControllerGetDesiredSize(controller);return 0>=desiredSize}function WritableStreamDefaultControllerError(controller,e){var stream=controller._controlledWritableStream;assert("writable"===stream._state||"closing"===stream._state),WritableStreamError(stream,e),controller._queue=[]}function streamBrandCheckException(name){return new TypeError("WritableStream.prototype."+name+" can only be used on a WritableStream")}function defaultWriterBrandCheckException(name){return new TypeError("WritableStreamDefaultWriter.prototype."+name+" can only be used on a WritableStreamDefaultWriter")}function defaultWriterLockException(name){return new TypeError("Cannot "+name+" a stream using a released writer")}function defaultWriterClosedPromiseInitialize(writer){writer._closedPromise=new Promise(function(resolve,reject){writer._closedPromise_resolve=resolve,writer._closedPromise_reject=reject})}function defaultWriterClosedPromiseInitializeAsRejected(writer,reason){writer._closedPromise=Promise.reject(reason),writer._closedPromise_resolve=void 0,writer._closedPromise_reject=void 0}function defaultWriterClosedPromiseInitializeAsResolved(writer){writer._closedPromise=Promise.resolve(void 0),writer._closedPromise_resolve=void 0,writer._closedPromise_reject=void 0}function defaultWriterClosedPromiseReject(writer,reason){assert(void 0!==writer._closedPromise_resolve),assert(void 0!==writer._closedPromise_reject),writer._closedPromise_reject(reason),writer._closedPromise_resolve=void 0,writer._closedPromise_reject=void 0}function defaultWriterClosedPromiseResetToRejected(writer,reason){assert(void 0===writer._closedPromise_resolve),assert(void 0===writer._closedPromise_reject),writer._closedPromise=Promise.reject(reason)}function defaultWriterClosedPromiseResolve(writer){assert(void 0!==writer._closedPromise_resolve),assert(void 0!==writer._closedPromise_reject),writer._closedPromise_resolve(void 0),writer._closedPromise_resolve=void 0,writer._closedPromise_reject=void 0}function defaultWriterReadyPromiseInitialize(writer){writer._readyPromise=new Promise(function(resolve,reject){writer._readyPromise_resolve=resolve,writer._readyPromise_reject=reject})}function defaultWriterReadyPromiseInitializeAsResolved(writer){writer._readyPromise=Promise.resolve(void 0),writer._readyPromise_resolve=void 0,writer._readyPromise_reject=void 0}function defaultWriterReadyPromiseReject(writer,reason){assert(void 0!==writer._readyPromise_resolve),assert(void 0!==writer._readyPromise_reject),writer._readyPromise_reject(reason),writer._readyPromise_resolve=void 0,writer._readyPromise_reject=void 0}function defaultWriterReadyPromiseReset(writer){assert(void 0===writer._readyPromise_resolve),assert(void 0===writer._readyPromise_reject),writer._readyPromise=new Promise(function(resolve,reject){writer._readyPromise_resolve=resolve,writer._readyPromise_reject=reject})}function defaultWriterReadyPromiseResetToRejected(writer,reason){assert(void 0===writer._readyPromise_resolve),assert(void 0===writer._readyPromise_reject),writer._readyPromise=Promise.reject(reason)}function defaultWriterReadyPromiseResolve(writer){assert(void 0!==writer._readyPromise_resolve),assert(void 0!==writer._readyPromise_reject),writer._readyPromise_resolve(void 0),writer._readyPromise_resolve=void 0,writer._readyPromise_reject=void 0}var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||!1,descriptor.configurable=!0,"value"in descriptor&&(descriptor.writable=!0),Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){return protoProps&&defineProperties(Constructor.prototype,protoProps),staticProps&&defineProperties(Constructor,staticProps),Constructor}}(),assert=require("assert"),_require=require("./helpers.js"),InvokeOrNoop=_require.InvokeOrNoop,PromiseInvokeOrNoop=_require.PromiseInvokeOrNoop,PromiseInvokeOrFallbackOrNoop=_require.PromiseInvokeOrFallbackOrNoop,ValidateAndNormalizeQueuingStrategy=_require.ValidateAndNormalizeQueuingStrategy,typeIsObject=_require.typeIsObject,_require2=require("./utils.js"),rethrowAssertionErrorRejection=_require2.rethrowAssertionErrorRejection,_require3=require("./queue-with-sizes.js"),DequeueValue=_require3.DequeueValue,EnqueueValueWithSize=_require3.EnqueueValueWithSize,GetTotalQueueSize=_require3.GetTotalQueueSize,PeekQueueValue=_require3.PeekQueueValue,WritableStream=function(){function WritableStream(){var underlyingSink=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],_ref=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],size=_ref.size,_ref$highWaterMark=_ref.highWaterMark,highWaterMark=void 0===_ref$highWaterMark?1:_ref$highWaterMark;_classCallCheck(this,WritableStream),this._state="writable",this._storedError=void 0,this._writer=void 0,this._writableStreamController=void 0,this._writeRequests=[];var type=underlyingSink.type;if(void 0!==type)throw new RangeError("Invalid type is specified");this._writableStreamController=new WritableStreamDefaultController(this,underlyingSink,size,highWaterMark)}return _createClass(WritableStream,[{key:"abort",value:function(reason){return IsWritableStream(this)===!1?Promise.reject(streamBrandCheckException("abort")):IsWritableStreamLocked(this)===!0?Promise.reject(new TypeError("Cannot abort a stream that already has a writer")):WritableStreamAbort(this,reason)}},{key:"getWriter",value:function(){if(IsWritableStream(this)===!1)throw streamBrandCheckException("getWriter");return AcquireWritableStreamDefaultWriter(this)}},{key:"locked",get:function(){if(IsWritableStream(this)===!1)throw streamBrandCheckException("locked");return IsWritableStreamLocked(this)}}]),WritableStream}();exports.WritableStream=WritableStream;var WritableStreamDefaultWriter=function(){function WritableStreamDefaultWriter(stream){if(_classCallCheck(this,WritableStreamDefaultWriter),IsWritableStream(stream)===!1)throw new TypeError("WritableStreamDefaultWriter can only be constructed with a WritableStream instance");if(IsWritableStreamLocked(stream)===!0)throw new TypeError("This stream has already been locked for exclusive writing by another writer");this._ownerWritableStream=stream,stream._writer=this;var state=stream._state;"writable"===state||"closing"===state?defaultWriterClosedPromiseInitialize(this):"closed"===state?defaultWriterClosedPromiseInitializeAsResolved(this):(assert("errored"===state,"state must be errored"),defaultWriterClosedPromiseInitializeAsRejected(this,stream._storedError)),"writable"===state&&WritableStreamDefaultControllerGetBackpressure(stream._writableStreamController)===!0?defaultWriterReadyPromiseInitialize(this):defaultWriterReadyPromiseInitializeAsResolved(this,void 0)}return _createClass(WritableStreamDefaultWriter,[{key:"abort",value:function(reason){return IsWritableStreamDefaultWriter(this)===!1?Promise.reject(defaultWriterBrandCheckException("abort")):void 0===this._ownerWritableStream?Promise.reject(defaultWriterLockException("abort")):WritableStreamDefaultWriterAbort(this,reason);
+}},{key:"close",value:function(){if(IsWritableStreamDefaultWriter(this)===!1)return Promise.reject(defaultWriterBrandCheckException("close"));var stream=this._ownerWritableStream;return void 0===stream?Promise.reject(defaultWriterLockException("close")):"closing"===stream._state?Promise.reject(new TypeError("cannot close an already-closing stream")):WritableStreamDefaultWriterClose(this)}},{key:"releaseLock",value:function(){if(IsWritableStreamDefaultWriter(this)===!1)throw defaultWriterBrandCheckException("releaseLock");var stream=this._ownerWritableStream;if(void 0!==stream){assert(void 0!==stream._writer);var state=stream._state,releasedException=new TypeError("Writer was released and can no longer be used to monitor the stream's closedness");"writable"===state||"closing"===state?defaultWriterClosedPromiseReject(this,releasedException):defaultWriterClosedPromiseResetToRejected(this,releasedException),"writable"===state&&WritableStreamDefaultControllerGetBackpressure(stream._writableStreamController)===!0?defaultWriterReadyPromiseReject(this,releasedException):defaultWriterReadyPromiseResetToRejected(this,releasedException),stream._writer=void 0,this._ownerWritableStream=void 0}}},{key:"write",value:function(chunk){if(IsWritableStreamDefaultWriter(this)===!1)return Promise.reject(defaultWriterBrandCheckException("write"));var stream=this._ownerWritableStream;return void 0===stream?Promise.reject(defaultWriterLockException("write to")):"closing"===stream._state?Promise.reject(new TypeError("Cannot write to an already-closed stream")):WritableStreamDefaultWriterWrite(this,chunk)}},{key:"closed",get:function(){return IsWritableStreamDefaultWriter(this)===!1?Promise.reject(defaultWriterBrandCheckException("closed")):this._closedPromise}},{key:"desiredSize",get:function(){if(IsWritableStreamDefaultWriter(this)===!1)throw defaultWriterBrandCheckException("desiredSize");if(void 0===this._ownerWritableStream)throw defaultWriterLockException("desiredSize");return WritableStreamDefaultWriterGetDesiredSize(this)}},{key:"ready",get:function(){return IsWritableStreamDefaultWriter(this)===!1?Promise.reject(defaultWriterBrandCheckException("ready")):this._readyPromise}}]),WritableStreamDefaultWriter}(),WritableStreamDefaultController=function(){function WritableStreamDefaultController(stream,underlyingSink,size,highWaterMark){if(_classCallCheck(this,WritableStreamDefaultController),IsWritableStream(stream)===!1)throw new TypeError("WritableStreamDefaultController can only be constructed with a WritableStream instance");if(void 0!==stream._writableStreamController)throw new TypeError("WritableStreamDefaultController instances can only be created by the WritableStream constructor");this._controlledWritableStream=stream,this._underlyingSink=underlyingSink,this._queue=[],this._started=!1,this._writing=!1;var normalizedStrategy=ValidateAndNormalizeQueuingStrategy(size,highWaterMark);this._strategySize=normalizedStrategy.size,this._strategyHWM=normalizedStrategy.highWaterMark;var backpressure=WritableStreamDefaultControllerGetBackpressure(this);backpressure===!0&&WritableStreamUpdateBackpressure(stream,backpressure);var controller=this,startResult=InvokeOrNoop(underlyingSink,"start",[this]);Promise.resolve(startResult).then(function(){controller._started=!0,WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller)},function(r){WritableStreamDefaultControllerErrorIfNeeded(controller,r)})["catch"](rethrowAssertionErrorRejection)}return _createClass(WritableStreamDefaultController,[{key:"error",value:function(e){if(IsWritableStreamDefaultController(this)===!1)throw new TypeError("WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController");var state=this._controlledWritableStream._state;if("closed"===state||"errored"===state)throw new TypeError("The stream is "+state+" and so cannot be errored");WritableStreamDefaultControllerError(this,e)}}]),WritableStreamDefaultController}()},{"./helpers.js":9,"./queue-with-sizes.js":10,"./utils.js":13,assert:2}]},{},[1])(1)}); \ No newline at end of file
diff --git a/www/external/screwdriver.js b/www/external/screwdriver.js
new file mode 100644
index 00000000..c6733776
--- /dev/null
+++ b/www/external/screwdriver.js
@@ -0,0 +1,151 @@
+;(function() {
+
+ if(typeof Blob === 'undefined')
+ return console.warn('Screw-FileReader is only meant to work in those' +
+ 'engine who already has some basic support for blob')
+
+ var blob = Blob.prototype
+ var fullStreamSupport = false
+ var basicStreamSupport = false
+ var fetchTransform = false
+ var URL = window.URL || window.webkitURL
+
+ function promisify(obj) {
+ return new Promise(function(resolve, reject) {
+ obj.onload =
+ obj.onerror = function(evt) {
+ obj.onload =
+ obj.onerror = null
+
+ evt.type === 'load'
+ ? resolve(obj.result || obj)
+ : reject(obj.error)
+ }
+ })
+ }
+
+ function toImage(url) {
+ var img = new Image
+ img.src = url
+ return promisify(img)
+ }
+
+ try {
+ new ReadableStream({})
+ basicStreamSupport = true
+ } catch (e) {}
+
+ try {
+ new ReadableStream({type: 'bytes'})
+ fullStreamSupport = true
+ } catch (e) {}
+
+ try {
+ (new Response(new Blob)).getReader()
+ fetchTransform = true
+ } catch (e) {}
+
+ if(!blob.arrayBuffer) {
+ blob.arrayBuffer = function arrayBuffer() {
+ var fr = new FileReader
+ fr.readAsArrayBuffer(this)
+ return promisify(fr)
+ }
+ }
+
+ if(!blob.text) {
+ blob.text = function text() {
+ var fr = new FileReader
+ fr.readAsText(this)
+ return promisify(fr)
+ }
+ }
+
+ if(!blob.dataURL) {
+ blob.dataURL = function dataURL() {
+ var fr = new FileReader
+ fr.readAsDataURL(this)
+ return promisify(fr)
+ }
+ }
+
+ if(!blob.url) {
+ blob.url = function url() {
+ return URL ? URL.createObjectURL(this) : null
+ }
+ }
+
+ if(!blob.json) {
+ blob.json = function json() {
+ return this.text().then(JSON.parse)
+ }
+ }
+
+ if(!blob.image) {
+ blob.image = function image() {
+ return Promise.resolve(this.url() || this.dataURL()).then(toImage)
+ }
+ }
+
+ if(!blob.stream) {
+ blob.stream =
+
+ fullStreamSupport ? function stream() {
+ var position = 0
+ var blob = this
+
+ return new ReadableStream({
+ type: 'bytes',
+ autoAllocateChunkSize: 524288,
+
+ pull: function (controller) {
+ var v = controller.byobRequest.view
+ var chunk = blob.slice(position, position + v.byteLength)
+ return chunk.arrayBuffer()
+ .then(function (buffer) {
+ let uint8array = new Uint8Array(buffer)
+ let bytesRead = uint8array.byteLength
+
+ position += bytesRead
+ v.set(uint8array)
+ controller.byobRequest.respond(bytesRead)
+
+ if(position >= blob.size)
+ controller.close()
+ })
+ }
+ })
+ }:
+
+ // basic stream support
+ basicStreamSupport ? function stream(blob){
+ var position = 0
+ var blob = this
+
+ return new ReadableStream({
+ pull: function (controller) {
+ var chunk = blob.slice(position, position + 524288)
+
+ return chunk.arrayBuffer().then(function (buffer) {
+ position += buffer.byteLength
+ let uint8array = new Uint8Array(buffer)
+ controller.enqueue(uint8array)
+
+ if(position == blob.size)
+ controller.close()
+ })
+ }
+ })
+ }:
+
+ // fetchTransform
+ fetchTransform ? function stream() {
+ return (new Response(this)).body
+ }:
+
+ function stream() {
+ throw new Error('Include https://github.com/creatorrr/web-streams-polyfill')
+ }
+ }
+
+}());