Bug 867445: Remove Test Pilot, r=gavin
authorBrian Smith <bsmith@mozilla.com>
Tue, 30 Apr 2013 17:30:44 -0700
changeset 141770 e1678abc3a8b2f2b8e576d43ca535fcf2f6de4f9
parent 141769 548558263c233fbd4d402309cdc0548f1a942407
child 141771 deea5f24e17a41ad498e1e5502d71ecb51c96413
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin
bugs867445
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 867445: Remove Test Pilot, r=gavin
addon-sdk/source/python-lib/cuddlefish/prefs.py
b2g/installer/package-manifest.in
browser/app/profile/extensions/Makefile.in
browser/app/profile/extensions/testpilot@labs.mozilla.com/chrome.manifest
browser/app/profile/extensions/testpilot@labs.mozilla.com/components/TestPilot.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/all-studies-window.xul
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.css
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.xul
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/debug.html
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/experiment-page.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/feedback-browser.xul
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.colorhelpers.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.colorhelpers.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.crosshair.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.crosshair.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.image.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.image.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.navigate.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.navigate.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.selection.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.selection.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.stack.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.stack.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.threshold.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.threshold.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/jquery.min.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/notificationBindings.xml
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/raw-data-dialog.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/raw-data-dialog.xul
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/screen.css
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/status-quit.html
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/status.html
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/survey-generator.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/take-survey.html
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/tp-browser-customNotifications.xul
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/tp-browser-popupNotifications.xul
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/tp-browser.xul
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/welcome-page.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/welcome.html
browser/app/profile/extensions/testpilot@labs.mozilla.com/content/window-utils.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/defaults/preferences/preferences.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/install.rdf.in
browser/app/profile/extensions/testpilot@labs.mozilla.com/instrument/chrome.manifest
browser/app/profile/extensions/testpilot@labs.mozilla.com/instrument/install.rdf
browser/app/profile/extensions/testpilot@labs.mozilla.com/instrument/instrument.jsm
browser/app/profile/extensions/testpilot@labs.mozilla.com/instrument/instrument.xul
browser/app/profile/extensions/testpilot@labs.mozilla.com/locale/en-US/main.dtd
browser/app/profile/extensions/testpilot@labs.mozilla.com/locale/en-US/main.properties
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/Observers.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/dbutils.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/experiment_data_store.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/extension-update.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/feedback.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/interface.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/jar-code-store.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/cuddlefish.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/file.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/memory.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/observer-service.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/plain-text-console.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/preferences-service.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/securable-module.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/timer.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/traceback.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/unit-test.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/unload.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/lib/url.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/log4moz.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/metadata.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/notifications.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/remote-experiment-loader.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/setup.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/string_sanitizer.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/modules/tasks.js
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/badge-default.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/bg.jpg
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/css/screen-standalone.css
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/dino_32x32.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/bg-status.jpg
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/callout.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/callout_continue.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/data1.jpg
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/data2.jpg
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/home_comments.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/home_computer.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/home_continue.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/home_quit.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/home_results.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/home_twitter.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/images/home_upcoming.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/logo.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/mozilla-logo.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/notification-tail-down.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/status-completed.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/status-ejected.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/status-missed.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/testPilot_200x200.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/testpilot_16x16.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/testpilot_32x32.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/tp-completedstudies-32x32.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/tp-currentstudies-32x32.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/tp-generic-32x32.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/tp-learned-32x32.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/tp-results-48x48.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/tp-settings-32x32.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/tp-study-48x48.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/all/tp-submit-48x48.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/linux/close_button.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/linux/feedback-broken-website.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/linux/feedback-frown-16x16.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/linux/feedback-idea.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/linux/feedback-rate.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/linux/feedback-smile-16x16.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/linux/feedback.css
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/close_button.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/feedback-broken-website.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/feedback-frown-16x16.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/feedback-idea.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/feedback-rate.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/feedback-smile-16x16.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/feedback.css
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/notification-tail-down.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/notification-tail-up.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/win/close_button.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/win/feedback-broken-website.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/win/feedback-frown-16x16.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/win/feedback-idea.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/win/feedback-rate.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/win/feedback-smile-16x16.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/win/feedback.css
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/win/notification-tail-down.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/win/notification-tail-up.png
browser/app/profile/extensions/testpilot@labs.mozilla.com/tests/test_data_store.js
browser/installer/Makefile.in
browser/installer/package-manifest.in
browser/locales/en-US/feedback/main.dtd
browser/locales/en-US/feedback/main.properties
browser/locales/jar.mn
build/automation.py.in
mobile/android/installer/package-manifest.in
testing/profiles/prefs_general.js
--- a/addon-sdk/source/python-lib/cuddlefish/prefs.py
+++ b/addon-sdk/source/python-lib/cuddlefish/prefs.py
@@ -51,19 +51,16 @@ DEFAULT_FENNEC_PREFS = {
 
 # When launching a temporary new Firefox profile, use these preferences.
 DEFAULT_FIREFOX_PREFS = {
     'browser.startup.homepage' : 'about:blank',
     'startup.homepage_welcome_url' : 'about:blank',
     'devtools.errorconsole.enabled' : True,
     'devtools.chrome.enabled' : True,
 
-    # Disable the feedback extension
-    'extensions.testpilot.runStudies' : False,
-
     # From:
     # http://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in#l388
     # Make url-classifier updates so rare that they won't affect tests.
     'urlclassifier.updateinterval' : 172800,
     # Point the url-classifier to a nonexistent local URL for fast failures.
     'browser.safebrowsing.provider.0.gethashURL' : 'http://localhost/safebrowsing-dummy/gethash',
     'browser.safebrowsing.provider.0.keyURL' : 'http://localhost/safebrowsing-dummy/newkey',
     'browser.safebrowsing.provider.0.updateURL' : 'http://localhost/safebrowsing-dummy/update',
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -561,19 +561,16 @@
 #endif
 
 ; [Browser Chrome Files]
 @BINPATH@/chrome/browser@JAREXT@
 @BINPATH@/chrome/browser.manifest
 @BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
 @BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png
 @BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/preview.png
-#if MOZ_UPDATE_CHANNEL == beta
-@BINPATH@/extensions/testpilot@labs.mozilla.com/*
-#endif
 @BINPATH@/chrome/toolkit@JAREXT@
 @BINPATH@/chrome/toolkit.manifest
 #ifdef XP_UNIX
 #ifndef XP_MACOSX
 @BINPATH@/chrome/icons/default/default16.png
 @BINPATH@/chrome/icons/default/default32.png
 @BINPATH@/chrome/icons/default/default48.png
 #endif
--- a/browser/app/profile/extensions/Makefile.in
+++ b/browser/app/profile/extensions/Makefile.in
@@ -10,17 +10,16 @@ VPATH      = @srcdir@
 
 DISTROEXT = $(call core_abspath,$(FINAL_TARGET))/distribution/extensions
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/config.mk
 
 ifneq (,$(filter beta,$(MOZ_UPDATE_CHANNEL)))
 EXTENSIONS = \
-  testpilot@labs.mozilla.com \
   $(NULL)
 
 all_xpis = $(foreach dir,$(EXTENSIONS),$(DISTROEXT)/$(dir).xpi)
 libs:: $(all_xpis)
 GARBAGE += $(all_xpis)
 
 define pp_one
 $(2) := $(2)
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/chrome.manifest
+++ /dev/null
@@ -1,20 +0,0 @@
-resource testpilot ./
-content testpilot content/
-locale testpilot en-US locale/en-US/
-skin testpilot skin skin/all/
-skin testpilot-os skin skin/linux/ os=Linux
-skin testpilot-os skin skin/linux/ os=SunOS
-skin testpilot-os skin skin/mac/ os=Darwin
-skin testpilot-os skin skin/win/ os=WINNT
-
-overlay chrome://browser/content/macBrowserOverlay.xul chrome://testpilot/content/browser.xul
-
-overlay chrome://browser/content/browser.xul chrome://testpilot/content/browser.xul
-
-style	chrome://global/content/customizeToolbar.xul	chrome://testpilot/content/browser.css
-# For the menubar on Mac
-overlay chrome://testpilot/content/all-studies-window.xul chrome://browser/content/macBrowserOverlay.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} os=Darwin
-
-component {e6e5e58f-7977-485a-b076-2f74bee2677b} components/TestPilot.js
-contract @mozilla.org/testpilot/service;1 {e6e5e58f-7977-485a-b076-2f74bee2677b}
-category profile-after-change testpilot @mozilla.org/testpilot/service;1
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/components/TestPilot.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-function TestPilotComponent() {}
-TestPilotComponent.prototype = {
-  classDescription: "Test Pilot Component",
-  contractID: "@mozilla.org/testpilot/service;1",
-  classID: Components.ID("{e6e5e58f-7977-485a-b076-2f74bee2677b}"),
-  _xpcom_categories: [{ category: "profile-after-change" }],
-  _startupTimer: null,
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
-                                         Ci.nsISupportsWeakReference]),
-
-  observe: function TPC__observe(subject, topic, data) {
-    let os = Cc["@mozilla.org/observer-service;1"].
-        getService(Ci.nsIObserverService);
-    switch (topic) {
-    case "profile-after-change":
-      os.addObserver(this, "sessionstore-windows-restored", true);
-      break;
-    case "sessionstore-windows-restored":
-      /* Stop oberver, to ensure that globalStartup doesn't get
-       * called more than once. */
-      os.removeObserver(this, "sessionstore-windows-restored");
-      /* Call global startup on a timer so that it's off of the main
-       * thread... delay a few seconds to give firefox time to finish
-       * starting up.
-       */
-      this._startupTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-      this._startupTimer.initWithCallback(
-        {notify: function(timer) {
-           Cu.import("resource://testpilot/modules/setup.js");
-           TestPilotSetup.globalStartup();
-         }}, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
-      break;
-    }
-  }
-};
-
-const components = [TestPilotComponent];
-var NSGetFactory, NSGetModule;
-if (XPCOMUtils.generateNSGetFactory)
-  NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
-else
-  NSGetModule = XPCOMUtils.generateNSGetModule(components);
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/all-studies-window.js
+++ /dev/null
@@ -1,445 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// TODO Show individual status page in new chromeless window as html with
-// background color set to "moz-dialog".
-
-const NO_STUDIES_IMG = "chrome://testpilot/skin/testPilot_200x200.png";
-const PROPOSE_STUDY_URL =
-  "https://wiki.mozilla.org/Labs/Test_Pilot#For_researchers";
-
-var TestPilotXulWindow = {
-  _stringBundle : null,
-
-  onSubmitButton: function(experimentId) {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    let task = TestPilotSetup.getTaskById(experimentId);
-    let button = document.getElementById("submit-button-" + task.id);
-
-    // Hide the upload button so it doesn't get clicked again...
-    let parent = button.parentNode;
-    while (parent.firstChild) {
-      parent.removeChild(parent.firstChild);
-    }
-    // Replace it with a message:
-    this.addLabel(
-      parent,
-      this._stringBundle.getString("testpilot.studiesWindow.uploading"));
-    let self = this;
-
-    task.upload( function(success) {
-      while (parent.firstChild) {
-        parent.removeChild(parent.firstChild);
-      }
-      if (success) {
-        self.addThanksMessage(parent);
-        // TODO or should we move it to 'finished studies' immediately?
-      } else {
-        // TODO a better error message?
-        self.addLabel(
-          parent,
-          self._stringBundle.getString(
-            "testpilot.studiesWindow.unableToReachServer"));
-      }
-    });
-
-  },
-
-  addThanksMessage: function(container) {
-    // Fill in status box with icon and message to show success
-    let hbox = document.createElement("hbox");
-    container.appendChild(this.makeSpacer());
-    container.appendChild(hbox);
-    this.addLabel(
-      container,
-      this._stringBundle.getString(
-        "testpilot.studiesWindow.thanksForContributing"));
-    container.appendChild(this.makeSpacer());
-    hbox.appendChild(this.makeSpacer());
-    this.addImg(hbox, "study-submitted");
-    hbox.appendChild(this.makeSpacer());
-  },
-
-  addXulLink: function (container, text, url, openInTab) {
-    let linkContainer = document.createElement("hbox");
-    let link = document.createElement("label");
-    let spacer = document.createElement("spacer");
-    link.setAttribute("value", text);
-    link.setAttribute("class", "text-link");
-    if (openInTab) {
-      link.setAttribute(
-        "onclick",
-        "if (event.button==0) { " +
-        "TestPilotWindowUtils.openInTab('" + url + "'); }");
-    } else {
-      link.setAttribute(
-        "onclick",
-        "if (event.button==0) { " +
-        "TestPilotWindowUtils.openChromeless('" + url + "'); }");
-    }
-    linkContainer.appendChild(link);
-    spacer.setAttribute("flex", "1");
-    linkContainer.appendChild(spacer);
-    container.appendChild(linkContainer);
-  },
-
-  addLabel: function(container, text, styleClass) {
-    let label = document.createElement("label");
-    label.setAttribute("value", text);
-    if (styleClass) {
-      label.setAttribute("class", styleClass);
-    }
-    container.appendChild(label);
-  },
-
-  addImg: function(container, iconClass) {
-    let newImg = document.createElement("image");
-    newImg.setAttribute("class", iconClass);
-    container.appendChild(newImg);
-  },
-
-  makeSpacer: function() {
-    let spacer = document.createElement("spacer");
-    spacer.setAttribute("flex", "1");
-    return spacer;
-  },
-
-  addThumbnail: function(container, imgUrl) {
-    let boundingBox = document.createElement("vbox");
-    boundingBox.setAttribute("class", "results-thumbnail");
-    let bBox2 = document.createElement("hbox");
-
-    boundingBox.appendChild(this.makeSpacer());
-    boundingBox.appendChild(bBox2);
-    boundingBox.appendChild(this.makeSpacer());
-
-    bBox2.appendChild(this.makeSpacer());
-    let newImg = document.createElement("image");
-    newImg.setAttribute("src", imgUrl);
-    newImg.setAttribute("class", "results-thumbnail");
-    bBox2.appendChild(newImg);
-    bBox2.appendChild(this.makeSpacer());
-
-    container.appendChild(boundingBox);
-  },
-
-  addProgressBar: function(container, percent) {
-    let progBar = document.createElement("progressmeter");
-    progBar.setAttribute("mode", "determined");
-    progBar.setAttribute("value", Math.ceil(percent).toString());
-    container.appendChild(progBar);
-  },
-
-  addDescription: function(container, title, paragraph) {
-    let desc = document.createElement("description");
-    desc.setAttribute("class", "study-title");
-    let txtNode = document.createTextNode(title);
-    desc.appendChild(txtNode);
-    container.appendChild(desc);
-
-    desc = document.createElement("description");
-    desc.setAttribute("class", "study-description");
-    desc.setAttribute("crop", "none");
-    txtNode = document.createTextNode(paragraph);
-    desc.appendChild(txtNode);
-    container.appendChild(desc);
-  },
-
-  addButton: function(container, label, id, onClickHandler) {
-    let button = document.createElement("button");
-    button.setAttribute("label", label);
-    button.setAttribute("id", id);
-    button.setAttribute("oncommand", onClickHandler);
-    container.appendChild(button);
-  },
-
-  _sortNewestFirst: function(experiments) {
-    experiments.sort(
-      function sortFunc(a, b) {
-        if (a.endDate && b.endDate) {
-          return b.endDate - a.endDate;
-        }
-        if (a.publishDate && b.publishDate) {
-          if (isNaN(a.publishDate) || isNaN(b.publishDate)) {
-            return 0;
-          }
-          return b.publishDate - a.publishDate;
-        }
-        return 0;
-      });
-    return experiments;
-  },
-
-  onLoad: function () {
-    Components.utils.import("resource://testpilot/modules/Observers.js");
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    Components.utils.import("resource://testpilot/modules/tasks.js");
-
-    this._stringBundle = document.getElementById("testpilot-stringbundle");
-    this.sizeWindow();
-    this._init(false);
-    Observers.add("testpilot:task:changed", this._onTaskStatusChanged, this);
-  },
-
-  onUnload: function() {
-    document.getElementById("settings-pane").writePreferences(true);
-    Observers.remove("testpilot:task:changed", this._onTaskStatusChanged, this);
-  },
-
-  _onTaskStatusChanged : function() {
-    this._init(true);
-  },
-
-  onTakeSurveyButton: function(taskId) {
-    let task = TestPilotSetup.getTaskById(taskId);
-    TestPilotWindowUtils.openChromeless(task.defaultUrl);
-    task.onDetailPageOpened();
-  },
-
-  _init: function(aReload) {
-    let experiments;
-    let ready = false;
-
-    // Are we done loading tasks?
-    if (TestPilotSetup.startupComplete) {
-      experiments = TestPilotSetup.getAllTasks();
-      if (experiments.length > 0 ) {
-        ready = true;
-      }
-    }
-
-    if (!ready) {
-      // If you opened the window before tasks are done loading, exit now
-      // but try again in a few seconds.
-      window.setTimeout(
-        function() { TestPilotXulWindow._init(aReload); }, 2000);
-      return;
-    }
-
-    let numFinishedStudies = 0;
-    let numCurrentStudies = 0;
-
-    /* Remove 'loading' message */
-    let msg = window.document.getElementById("still-loading-msg");
-    msg.setAttribute("hidden", "true");
-
-    if (aReload) {
-      /* If we're reloading, start by clearing out any old stuff already
-       * present in the listboxes. */
-      let listboxIds =
-        ["current-studies-listbox", "finished-studies-listbox",
-         "study-results-listbox"];
-      for (let i = 0; i < listboxIds.length; i++) {
-        let listbox = document.getElementById(listboxIds[i]);
-
-        while (listbox.lastChild) {
-          listbox.removeChild(listbox.lastChild);
-        }
-      }
-    }
-
-    experiments = this._sortNewestFirst(experiments);
-
-    for (let i = 0; i < experiments.length; i++) {
-      let task = experiments[i];
-      let newRow = document.createElement("richlistitem");
-      newRow.setAttribute("class", "tp-study-list");
-
-      this.addThumbnail(newRow, task.thumbnail);
-
-      let textVbox = document.createElement("vbox");
-      newRow.appendChild(textVbox);
-
-      let openInTab = (task.taskType == TaskConstants.TYPE_LEGACY);
-
-      this.addDescription(textVbox, task.title, task.summary);
-      this.addXulLink(
-        textVbox, this._stringBundle.getString("testpilot.moreInfo"),
-        task.defaultUrl, openInTab);
-
-      // Create the rightmost status area, depending on status:
-      let statusVbox = document.createElement("vbox");
-      if (task.status == TaskConstants.STATUS_FINISHED) {
-        this.addLabel(
-          statusVbox,
-          this._stringBundle.getFormattedString(
-            "testpilot.studiesWindow.finishedOn",
-            [(new Date(task.endDate)).toLocaleDateString()]));
-        this.addButton(statusVbox,
-          this._stringBundle.getString("testpilot.submit"),
-          "submit-button-" + task.id,
-          "TestPilotXulWindow.onSubmitButton(" + task.id + ");");
-      }
-      if (task.status == TaskConstants.STATUS_CANCELLED) {
-        let hbox = document.createElement("hbox");
-        newRow.setAttribute("class", "tp-opted-out");
-        statusVbox.appendChild(this.makeSpacer());
-        statusVbox.appendChild(hbox);
-        this.addLabel(
-          statusVbox,
-          this._stringBundle.getString("testpilot.studiesWindow.canceledStudy"));
-        statusVbox.appendChild(this.makeSpacer());
-        hbox.appendChild(this.makeSpacer());
-        this.addImg(hbox, "study-canceled");
-        hbox.appendChild(this.makeSpacer());
-      }
-      if (task.status == TaskConstants.STATUS_NEW ||
-          task.status == TaskConstants.STATUS_PENDING ) {
-        newRow.setAttribute("class", "tp-new-results");
-
-        if (task.taskType == TaskConstants.TYPE_SURVEY) {
-          this.addButton(
-            statusVbox,
-            this._stringBundle.getString("testpilot.takeSurvey"),
-            "survey-button",
-            "TestPilotXulWindow.onTakeSurveyButton('" + task.id + "');");
-        } else if (task.taskType == TaskConstants.TYPE_EXPERIMENT) {
-          if (task.startDate) {
-            this.addLabel(
-              statusVbox,
-              this._stringBundle.getFormattedString(
-                "testpilot.studiesWindow.willStart",
-                [(new Date(task.startDate)).toLocaleDateString()]));
-          }
-        }
-      }
-      if (task.status == TaskConstants.STATUS_IN_PROGRESS ||
-          task.status == TaskConstants.STATUS_STARTING) {
-
-        if (task.taskType == TaskConstants.TYPE_SURVEY) {
-          this.addButton(
-            statusVbox,
-            this._stringBundle.getString("testpilot.takeSurvey"),
-            "survey-button",
-            "TestPilotXulWindow.onTakeSurveyButton('" + task.id + "');");
-        } else if (task.taskType == TaskConstants.TYPE_EXPERIMENT) {
-          this.addLabel(
-            statusVbox,
-            this._stringBundle.getString(
-             "testpilot.studiesWindow.gatheringData"));
-             let now = (new Date()).getTime();
-          let progress =
-            100 * (now - task.startDate) / (task.endDate - task.startDate);
-          this.addProgressBar(statusVbox, progress);
-          this.addLabel(
-            statusVbox,
-            this._stringBundle.getFormattedString(
-              "testpilot.studiesWindow.willFinish",
-              [(new Date(task.endDate)).toLocaleDateString()]));
-        }
-      }
-      if (task.status >= TaskConstants.STATUS_SUBMITTED) {
-        if (task.taskType == TaskConstants.TYPE_RESULTS) {
-          let maintask = TestPilotSetup.getTaskById(task.relatedStudyId);
-          if (maintask && maintask.status >= TaskConstants.STATUS_SUBMITTED) {
-            this.addThanksMessage(statusVbox);
-          }
-        } else {
-          if (task.status == TaskConstants.STATUS_MISSED) {
-            // Icon for missed studies
-            let hbox = document.createElement("hbox");
-            newRow.setAttribute("class", "tp-opted-out");
-            statusVbox.appendChild(this.makeSpacer());
-            statusVbox.appendChild(hbox);
-            this.addLabel(
-              statusVbox,
-              this._stringBundle.getString("testpilot.studiesWindow.missedStudy"));
-            statusVbox.appendChild(this.makeSpacer());
-            hbox.appendChild(this.makeSpacer());
-            this.addImg(hbox, "study-missed");
-            hbox.appendChild(this.makeSpacer());
-          } else {
-            this.addThanksMessage(statusVbox);
-            numFinishedStudies ++;
-          }
-        }
-      }
-      let spacer = document.createElement("spacer");
-      spacer.setAttribute("flex", "1");
-      newRow.appendChild(spacer);
-      newRow.appendChild(statusVbox);
-
-      // Use status to decide which panel to add this to:
-      let rowset;
-      if (task.taskType == TaskConstants.TYPE_RESULTS) {
-        rowset = document.getElementById("study-results-listbox");
-      } else if (task.status > TaskConstants.STATUS_FINISHED) {
-        rowset = document.getElementById("finished-studies-listbox");
-      } else {
-        rowset = document.getElementById("current-studies-listbox");
-        numCurrentStudies++;
-      }
-
-      // TODO further distinguish by background colors.
-      rowset.appendChild(newRow);
-    }
-
-    // If there are no current studies, show a message about upcoming
-    // studies:
-    if (numCurrentStudies == 0) {
-      let newRow = document.createElement("richlistitem");
-      newRow.setAttribute("class", "tp-study-list");
-      this.addThumbnail(newRow, NO_STUDIES_IMG);
-      let textVbox = document.createElement("vbox");
-      textVbox.setAttribute("class", "pilot-largetext");
-      newRow.appendChild(textVbox);
-      this.addDescription(
-        textVbox, "",
-        this._stringBundle.getString("testpilot.studiesWindow.noStudies"));
-      this.addXulLink(
-        textVbox,
-        this._stringBundle.getString("testpilot.studiesWindow.proposeStudy"),
-        PROPOSE_STUDY_URL, true);
-      document.getElementById("current-studies-listbox").appendChild(newRow);
-    }
-
-    // Show number of studies the user finished on badge:
-    document.getElementById("num-finished-badge").setAttribute(
-      "value", numFinishedStudies);
-  },
-
-  sizeWindow: function() {
-    // Size listboxes based on available screen size, then size window to fit
-    // list boxes.
-    let currList = document.getElementById("current-studies-listbox");
-    let finList = document.getElementById("finished-studies-listbox");
-    let resultsList = document.getElementById("study-results-listbox");
-
-    let screenWidth = window.screen.availWidth;
-    let screenHeight = window.screen.availHeight;
-    let width = screenWidth >= 800 ? 700 : screenWidth - 100;
-    let height = screenHeight >= 800 ? 700 : screenHeight - 100;
-
-    height -= 130; // Or whatever is height of title bar plus windowdragbox
-
-    currList.width = width;
-    currList.height = height;
-    finList.width = width;
-    finList.height = height;
-    resultsList.width = width;
-    resultsList.height = height;
-    window.sizeToContent();
-  },
-
-  focusPane: function(paneIndex) {
-    document.getElementById("tp-xulwindow-deck").selectedIndex = paneIndex;
-
-    // When you focus the 'study findings' tab, any results there which
-    // are still marked "new" should have their status changed as the user
-    // is considered to have seen them.
-    if (paneIndex == 2) {
-      Components.utils.import("resource://testpilot/modules/setup.js");
-      Components.utils.import("resource://testpilot/modules/tasks.js");
-
-      let experiments = TestPilotSetup.getAllTasks();
-      for each (let experiment in experiments) {
-        if (experiment.taskType == TaskConstants.TYPE_RESULTS) {
-          if (experiment.status == TaskConstants.STATUS_NEW) {
-            experiment.changeStatus(TaskConstants.STATUS_ARCHIVED, true);
-          }
-        }
-      }
-    }
-  }
-};
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/all-studies-window.xul
+++ /dev/null
@@ -1,142 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
-<?xml-stylesheet href="chrome://global/skin/preferences.css" type="text/css"?>
-<?xml-stylesheet href="chrome://mozapps/content/extensions/extensions.css"
-  type="text/css"?>
-<?xml-stylesheet href="chrome://testpilot/content/browser.css" type="text/css"?>
-
-
-<!DOCTYPE prefwindow [
-  <!ENTITY % testpilotDTD SYSTEM "chrome://testpilot/locale/main.dtd">
-    %testpilotDTD;
-]>
-
-<prefwindow id="test-pilot-all-studies-window"
-  title="&testpilot.studiesWindow.title;"
-  windowtype="extensions:testpilot:all_studies_window"
-  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-  onload="TestPilotXulWindow.onLoad();"
-  onunload="TestPilotXulWindow.onUnload();">
-
-  <script src="chrome://testpilot/content/window-utils.js"
-    type="application/javascript;version=1.8"/>
-  <script src="chrome://testpilot/content/all-studies-window.js"
-    type="application/javascript;version=1.8"/>
-
-  <stringbundleset id="stringbundleset">
-    <stringbundle id="testpilot-stringbundle"
-      src="chrome://testpilot/locale/main.properties" />
-  </stringbundleset>
-
-  <vbox flex="1">
-    <windowdragbox orient="vertical">
-      <radiogroup id="tp-radiogroup" orient="horizontal" role="listbox"
-        class="paneSelector"
-        onselect="TestPilotXulWindow.focusPane(this.selectedIndex);">
-        <radio pane="current-studies-pane-button" orient="vertical">
-          <image class="paneButtonIcon" />
-          <label class="paneButtonLabel"
-            value="&testpilot.studiesWindow.currentStudies.label;"/>
-        </radio>
-        <radio pane="finished-studies-pane-button" orient="vertical">
-          <stack align="center" pack="center">
-            <hbox align="center" pack="center">
-             <image class="paneButtonIcon" />
-            </hbox>
-            <label id="num-finished-badge" class="pane-button-badge"/>
-          </stack>
-          <label class="paneButtonLabel"
-            value="&testpilot.studiesWindow.finishedStudies.label;"/>
-        </radio>
-        <radio pane="study-results-pane-button" orient="vertical">
-          <image class="paneButtonIcon" />
-          <label class="paneButtonLabel"
-            value="&testpilot.studiesWindow.studyFindings.label;"/>
-        </radio>
-        <radio pane="settings-pane-button" orient="vertical">
-          <image class="paneButtonIcon" />
-          <label class="paneButtonLabel"
-            value="&testpilot.studiesWindow.settings.label;"/>
-        </radio>
-      </radiogroup>
-    </windowdragbox>
-
-    <deck id="tp-xulwindow-deck" flex="1">
-      <prefpane id="current-studies-pane" class="tp-tab-panel">
-        <richlistbox id="current-studies-listbox" class="tp-study-list"
-          disabled="true">
-          <richlistitem id="still-loading-msg" class="tp-study-list">
-            <description class="pilot-largetext">
-              &testpilot.studiesWindow.stillLoadingMessage;
-            </description>
-          </richlistitem>
-        </richlistbox>
-      </prefpane>
-
-      <prefpane id="finished-studies-pane" class="tp-tab-panel">
-        <richlistbox id="finished-studies-listbox" class="tp-study-list"
-          disabled="true"/>
-      </prefpane>
-
-      <prefpane id="study-results-pane" class="tp-tab-panel">
-        <richlistbox id="study-results-listbox" class="tp-study-list"
-          disabled="true"/>
-      </prefpane>
-
-      <prefpane id="settings-pane" class="tp-tab-panel">
-        <preferences>
-          <preference id="notify-finished" type="bool"
-                      name="extensions.testpilot.popup.showOnStudyFinished"/>
-          <preference id="notify-new" type="bool"
-                      name="extensions.testpilot.popup.showOnNewStudy"/>
-          <preference id="notify-results" type="bool"
-                      name="extensions.testpilot.popup.showOnNewResults"/>
-          <preference id="always-submit-data" type="bool"
-                      name="extensions.testpilot.alwaysSubmitData"/>
-        </preferences>
-        <vbox style="padding: 12px;">
-          <groupbox>
-            <caption label="&testpilot.settings.dataSubmission.label;" />
-            <checkbox label="&testpilot.settings.alwaysSubmitData.label;"
-                      preference="always-submit-data"/>
-          </groupbox>
-          <groupbox>
-            <caption label="&testpilot.settings.notifications.label;" />
-            <label value="&testpilot.settings.notifyWhen.label;"/>
-            <hbox>
-              <separator orient="vertical" />
-              <vbox>
-                <checkbox label="&testpilot.settings.readyToSubmit.label;"
-                          preference="notify-finished"/>
-                <checkbox label="&testpilot.settings.newStudy.label;"
-                          preference="notify-new"/>
-                <checkbox label="&testpilot.settings.hasNewResults.label;"
-                          preference="notify-results"/>
-              </vbox>
-            </hbox>
-          </groupbox>
-        </vbox>
-      </prefpane>
-    </deck>
-  </vbox>
-
-  <!-- For the menubar on mac, the below elements are needed for
-       macBrowserOverlay.xul to overlay this window. -->
-  <stringbundleset id="stringbundleset"/>
-
-  <commandset id="mainCommandSet"/>
-  <commandset id="baseMenuCommandSet"/>
-  <commandset id="placesCommands"/>
-
-  <broadcasterset id="mainBroadcasterSet"/>
-
-  <keyset id="mainKeyset"/>
-  <keyset id="baseMenuKeyset"/>
-
-  <menubar id="main-menubar" style="border:none !important;margin:0;padding:0;"/>
-
-</prefwindow>
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.css
+++ /dev/null
@@ -1,245 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Toolbar Button */
-
-#feedback-menu-button {
-  -moz-box-orient: horizontal;
-}
-
-#feedback-menu-button .toolbarbutton-text {
-  display: -moz-box;
-  margin: 0;
-  color: -moz-dialogtext;
-  text-shadow: none;
-}
-
-#feedback-menu-button .toolbarbutton-icon {
-  display: none;
-}
-
-#feedback-menu-button .toolbarbutton-menu-dropmarker {
-  -moz-padding-start: 5px;
-}
-
-#tp-notification-popup-icon {
-  list-style-image: url("chrome://testpilot/skin/testpilot_16x16.png");
-}
-
-/* Popup Bounding Box */
-#pilot-notification-popup {
-  -moz-appearance: none;
-  -moz-window-shadow: none;
-  background-color: transparent;
-  margin-top: -6px;
-  margin-right: -3px;
-  width: 480px;
-  /* FIXES: #725850  based on #717262
-  /* Needed whilst we support Gecko < 13 */
-  border-image: url(chrome://testpilot-os/skin/notification-tail-up.png) 26 56 22 18 / 26px 56px 22px 18px round stretch;
-  /* Supported in Gecko >= 13 */
-  border-image: url(chrome://testpilot-os/skin/notification-tail-up.png) 26 50 22 18 fill stretch;
-  border-width: 26px 56px 22px 18px;
-  border-style: solid;
-}
-
-
-.pilot-notification-popup-container {
-  -moz-appearance: none;
-  margin-right: -42px;
-  padding: 0px 5px 5px 5px;
-  font-size: 14px;
-}
-
-.pilot-notification-toprow {
-  margin-bottom: 12px;
-}
-
-#pilot-notification-text {
-  margin-bottom: 5px;
-}
-
-#pilot-notification-link {
-  margin-bottom: 5px;
-  text-decoration: underline;
-  cursor: pointer;
-}
-
-#pilot-notification-close {
-  list-style-image: url("chrome://testpilot-os/skin/close_button.png");
-  -moz-image-region: rect(0px, 14px, 14px, 0px);
-  width: 14px;
-  height: 14px;
-}
-
-#pilot-notification-close:hover {
-  -moz-image-region: rect(0px, 28px, 14px, 14px);
-}
-
-#pilot-notification-close:hover:active {
-  -moz-image-region: rect(0px, 42px, 14px, 28px);
-}
-
-.pilot-notify-me-when[disabled="true"] {
-  color: -moz-dialogtext;
-}
-.pilot-title {
-  font-size: 25px;
-}
-
-image.study-finished {
-  list-style-image: url("chrome://testpilot/skin/tp-submit-48x48.png");
-  height: 48px;
-  width: 48px;
-  margin-right: 8px;
-}
-
-image.study-submitted {
-  list-style-image: url("chrome://testpilot/skin/status-completed.png");
-  height: 32px;
-  width: 64px;
-  margin-right: 8px;
-}
-
-image.study-canceled {
-  list-style-image: url("chrome://testpilot/skin/status-ejected.png");
-  height: 32px;
-  width: 64px;
-  margin-right: 8px;
-}
-
-image.study-missed {
-  list-style-image: url("chrome://testpilot/skin/status-missed.png");
-  height: 32px;
-  width: 64px;
-  margin-right: 8px;
-}
-
-image.new-study {
-  list-style-image: url("chrome://testpilot/skin/tp-study-48x48.png");
-  height: 48px;
-  width: 48px;
-  margin-right: 8px;
-}
-
-image.new-results {
-  list-style-image: url("chrome://testpilot/skin/tp-results-48x48.png");
-  height: 48px;
-  width: 48px;
-  margin-right: 8px;
-}
-
-image.update-extension {
-  list-style-image: url("chrome://testpilot/skin/testpilot_32x32.png");
-  height: 48px;
-  width: 48px;
-  margin-right: 8px;
-}
-
-image.study-result {
-  list-style-image: url("chrome://testpilot/skin/badge-default.png");
-  height: 96px;
-  width: 96px;
-  margin-right: 8px;
-}
-
-/* All studies window */
-.pilot-largetext {
-  font-size: 16px;
-}
-
-#test-pilot-all-studies-window > .prefWindow-dlgbuttons {
-    display: none;
-}
-
-.paneSelector {
-    margin: 0 !important;
-}
-
-.paneSelector radio[pane="current-studies-pane-button"] .paneButtonIcon {
-    list-style-image: url("chrome://testpilot/skin/tp-currentstudies-32x32.png");
-    padding-top: 3px;
-}
-.paneSelector radio[pane="finished-studies-pane-button"] .paneButtonIcon {
-    list-style-image: url("chrome://testpilot/skin/tp-completedstudies-32x32.png");
-    padding-top: 3px;
-}
-.paneSelector radio[pane="study-results-pane-button"] .paneButtonIcon {
-    list-style-image: url("chrome://testpilot/skin/tp-learned-32x32.png");
-    padding-top: 3px;
-}
-.paneSelector radio[pane="settings-pane-button"] .paneButtonIcon {
-    list-style-image: url("chrome://testpilot/skin/tp-settings-32x32.png");
-    padding-top: 3px;
-}
-
-.pane-button-badge {
-    background-color: green;
-    color: white;
-    font-weight: bold;
-    padding: 2px;
-    border-radius: 100%;
-    margin-right: 25px;
-    margin-bottom: 13px;
-}
-
-richlistbox.tp-study-list {
-    overflow: auto;
-    margin: 0px;
-}
-
-.tp-tab-panel {
-    background-color: -moz-dialog;
-    padding: 0px;
-}
-
-description.study-description {
-    width: 350px;
-}
-
-description.study-title {
-    width: 350px;
-    font-size: 20px;
-    text-align: left;
-    margin-top: 10px;
-}
-
-richlistitem.tp-study-list {
-    min-height: 120px;
-    color: black;
-    background-color: -moz-dialog;
-}
-
-richlistitem.tp-new-results {
-    min-height: 120px;
-    color: black;
-    background-color: LemonChiffon;
-}
-
-richlistitem.tp-opted-out {
-    min-height: 120px;
-    color: grey;
-    background-color: -moz-dialog;
-}
-
-vbox.results-thumbnail {
-    height: 120px;
-    width: 120px;
-}
-
-image.results-thumbnail {
-    max-height: 90px;
-    max-width:  90px;
-    margin: 10px;
-}
-
-prefpane .groupbox-body {
-  -moz-appearance: none;
-  padding: 8px 4px 4px 4px;
-}
-
-prefpane .groupbox-title {
-  background: url("chrome://global/skin/50pct_transparent_grey.png") repeat-x bottom left;
-  margin-bottom: 4px;
-}
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var TestPilotMenuUtils;
-
-(function() {
-  var Cc = Components.classes;
-  var Cu = Components.utils;
-  var Ci = Components.interfaces;
-
-  Cu.import("resource://testpilot/modules/setup.js");
-
-  TestPilotMenuUtils = {
-    updateSubmenu: function() {
-      let ntfyMenuFinished =
-        document.getElementById("pilot-menu-notify-finished");
-      let ntfyMenuNew = document.getElementById("pilot-menu-notify-new");
-      let ntfyMenuResults = document.getElementById("pilot-menu-notify-results");
-      let alwaysSubmitData =
-        document.getElementById("pilot-menu-always-submit-data");
-      let Application = Cc["@mozilla.org/fuel/application;1"]
-                      .getService(Ci.fuelIApplication);
-      ntfyMenuFinished.setAttribute("checked", Application.prefs.getValue(
-                                    POPUP_SHOW_ON_FINISH, false));
-      ntfyMenuNew.setAttribute("checked", Application.prefs.getValue(
-                                POPUP_SHOW_ON_NEW, false));
-      ntfyMenuResults.setAttribute("checked", Application.prefs.getValue(
-                                    POPUP_SHOW_ON_RESULTS, false));
-      alwaysSubmitData.setAttribute("checked", Application.prefs.getValue(
-                                     ALWAYS_SUBMIT_DATA, false));
-    },
-
-    togglePref: function(id) {
-      let prefName = "extensions.testpilot." + id;
-      let oldVal = Application.prefs.getValue(prefName, false);
-      Application.prefs.setValue( prefName, !oldVal);
-
-      // If you turn on or off the global pref, startup or shutdown test pilot
-      // accordingly:
-      if (prefName == RUN_AT_ALL_PREF) {
-        if (oldVal == true) {
-          TestPilotSetup.globalShutdown();
-        }
-        if (oldVal == false) {
-          TestPilotSetup.globalStartup();
-        }
-      }
-    },
-
-    onPopupShowing: function(event) {
-      this._setMenuLabels();
-    },
-
-    onPopupHiding: function(event) {
-      let target = event.target;
-      if (target.id == "pilot-menu-popup") {
-        let menu = document.getElementById("pilot-menu");
-        if (target.parentNode != menu) {
-          menu.appendChild(target);
-        }
-      }
-    },
-
-    _setMenuLabels: function() {
-      // Make the enable/disable User Studies menu item show the right label
-      // for the current status...
-      let runStudiesToggle = document.getElementById("feedback-menu-enable-studies");
-      if (runStudiesToggle) {
-        let currSetting = Application.prefs.getValue("extensions.testpilot.runStudies",
-                                                     true);
-
-        let stringBundle = Cc["@mozilla.org/intl/stringbundle;1"].
-          getService(Ci.nsIStringBundleService).
-          createBundle("chrome://testpilot/locale/main.properties");
-
-        if (currSetting) {
-          runStudiesToggle.setAttribute("label",
-            stringBundle.GetStringFromName("testpilot.turnOff"));
-        } else {
-          runStudiesToggle.setAttribute("label",
-            stringBundle.GetStringFromName("testpilot.turnOn"));
-        }
-      }
-
-      let studiesMenuItem = document.getElementById("feedback-menu-show-studies");
-      studiesMenuItem.setAttribute("disabled",
-                                   !Application.prefs.getValue(RUN_AT_ALL_PREF, true));
-    },
-
-    onMenuButtonMouseDown: function(attachPointId) {
-      if (!attachPointId) {
-        attachPointId = "pilot-notifications-button";
-      }
-      let menuPopup = document.getElementById("pilot-menu-popup");
-      let menuButton = document.getElementById(attachPointId);
-
-      // TODO failing here with "menuPopup is null" for Tracy
-      if (menuPopup.parentNode != menuButton)
-        menuButton.appendChild(menuPopup);
-
-      let alignment;
-      // Menu should appear above status bar icon, but below Feedback button
-      if (attachPointId == "pilot-notifications-button") {
-        alignment = "before_start";
-      } else {
-        alignment = "after_end";
-      }
-
-      menuPopup.openPopup(menuButton, alignment, 0, 0, true);
-    }
-  };
-
-
-  var TestPilotWindowHandlers = {
-    onWindowLoad: function() {
-      // Customize the interface of the newly opened window.
-      Cu.import("resource://testpilot/modules/interface.js");
-      TestPilotUIBuilder.buildCorrectInterface(window);
-
-      /* "Hold" window load events for TestPilotSetup, passing them along only
-       * after startup is complete.  It's hacky, but the benefit is that
-       * TestPilotSetup.onWindowLoad can treat all windows the same no matter
-       * whether they opened with Firefox on startup or were opened later. */
-      if (TestPilotSetup && TestPilotSetup.startupComplete) {
-        TestPilotSetup.onWindowLoad(window);
-      } else {
-        let observerSvc = Cc["@mozilla.org/observer-service;1"]
-                             .getService(Ci.nsIObserverService);
-        let observer = {
-          observe: function(subject, topic, data) {
-            observerSvc.removeObserver(this, "testpilot:startup:complete");
-            TestPilotSetup.onWindowLoad(window);
-          }
-        };
-        observerSvc.addObserver(observer, "testpilot:startup:complete", false);
-      }
-    },
-
-    onWindowUnload: function() {
-      TestPilotSetup.onWindowUnload(window);
-    }
-  };
-
-  window.addEventListener("load", TestPilotWindowHandlers.onWindowLoad, false);
-  window.addEventListener("unload", TestPilotWindowHandlers.onWindowUnload, false);
-}());
-
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/browser.xul
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<?xml-stylesheet href="chrome://testpilot/content/browser.css" type="text/css"?>
-<?xml-stylesheet href="chrome://testpilot-os/skin/feedback.css" type="text/css"?>
-
-<!DOCTYPE overlay [
-  <!ENTITY % testpilotDTD SYSTEM "chrome://testpilot/locale/main.dtd">
-    %testpilotDTD;
-]>
-
-<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-<script src="chrome://testpilot/content/browser.js"
-  type="application/x-javascript" />
-<script src="chrome://testpilot/content/window-utils.js"
-  type="application/x-javascript" />
-
-<toolbarpalette id="BrowserToolbarPalette">
-  <toolbarbutton id="feedback-menu-button"
-    type="menu" class="toolbarbutton-1" label="&testpilot.feedbackbutton.label;"
-    onmousedown="event.preventDefault();
-    TestPilotMenuUtils.onMenuButtonMouseDown('feedback-menu-button');"/>
-
-</toolbarpalette>
-
-</overlay>
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/debug.html
+++ /dev/null
@@ -1,295 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-<html> <head>
-<title>Test Pilot Debug Page</title>
-<script type="text/javascript" src="jquery.min.js"></script>
-<script src="experiment-page.js" type="application/javascript;version=1.8"></script>
-<script type="application/javascript;version=1.8">
-
-  var numstartupattempts=0;
-  function startup() {
-      numstartupattempts += 1;
-      dump('numattempts: ' + numstartupattempts + "\n");
-      var dropsuccess = populateFileDropdown();
-      if (! dropsuccess) {
-          $('h1#status').fadeIn('slow','linear');
-          window.setTimeout(function() {startup()}, 2000); // try again!
-      } else {
-          showSelectedTaskStatus()
-          showIndexFileDropdown();
-          $('h1#status').fadeOut("slow", "linear");
-      };
-  };
-
-  function getEid() {
-    var selector = document.getElementById("task-selector");
-    var i = selector.selectedIndex;
-    return selector.options[i].getAttribute("value");
-  }
-
-  function setTaskStatus() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    var newStatus = document.getElementById("status-code").value;
-    newStatus = parseInt(newStatus);
-    var task = TestPilotSetup.getTaskById(getEid());
-    task.changeStatus(newStatus, false);
-  }
-
-  function reloadAllExperiments() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    TestPilotSetup.reloadRemoteExperiments(function(success) {
-      let errors = TestPilotSetup._remoteExperimentLoader.getLoadErrors();
-      let str;
-      if (errors.length > 0) {
-        str = "<ul>";
-        for each (let errStr in errors) {
-          str += "<li>" + errStr + "</li>";
-        }
-        str += "</ul>";
-      } else {
-        str = "All experiments reloaded, no errors.";
-      }
-      document.getElementById("debug").innerHTML = str;
-    });
-  }
-
-  function runUnitTests() {
-   Components.utils.import("resource://testpilot/tests/test_data_store.js");
-   runAllTests();
-  }
-
-  function testJarStore() {
-    var Cuddlefish = {};
-    Components.utils.import("resource://testpilot/modules/lib/cuddlefish.js",
-                        Cuddlefish);
-    var loader = new Cuddlefish.Loader(
-      {rootPaths: ["resource://testpilot/modules/",
-                   "resource://testpilot/modules/lib/"]});
-    var jarStoreModule = loader.require("jar-code-store");
-    var SecurableModule = loader.require("securable-module");
-    var jarStore = new jarStoreModule.JarStore();
-
-    // OK now watch this!  It's gonna be awesome!
-    var clientLoader = Cuddlefish.Loader(
-      {fs: new SecurableModule.CompositeFileSystem(
-         [jarStore, loader.fs])});
-    dump("Debug page Requiring toolbar study.\n");
-    var toolbarStudy = clientLoader.require("toolbar-study");
-
-  }
-
-  function remindMe() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    TestPilotSetup._notifyUserOfTasks();
-    //TestPilotSetup._doHousekeeping();
-  }
-
-  function getCodeStorage() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    var loader = TestPilotSetup._remoteExperimentLoader;
-    if (! loader) {return undefined;}
-    return loader._jarStore;
-  }
-
-  function getSelectedFilename() {
-    var selector = document.getElementById("file-selector");
-    var i = selector.selectedIndex;
-    return selector.options[i].text;
-  }
-
-  function loadExperimentCode() {
-    var filename = getSelectedFilename();
-    var codeStore = getCodeStorage();
-    var textArea = document.getElementById("experiment-code-area");
-    var path = codeStore.resolveModule(null, filename);
-    code = codeStore.getFile(path).contents;
-    textArea.value = code;
-  }
-
-  function saveAndRun() {
-    var filename = getSelectedFilename();
-    var codeStore = getCodeStorage();
-    var path = codeStore.resolveModule(null, filename);
-    var textArea = document.getElementById("experiment-code-area");
-    codeStore.setLocalOverride(path, textArea.value);
-    reloadAllExperiments();
-  }
-
-  function showMetaData() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    let task = TestPilotSetup.getTaskById(getEid());
-    let json = task._prependMetadataToJSON(function(json) {
-      document.getElementById("debug").innerHTML = json;
-    });
-  }
-
-  function makeThereBeAPopup() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    var task = TestPilotSetup.getTaskById(getEid());
-    var text = "Sample popup for " + task.title;
-    TestPilotSetup._showNotification(task, false, text, "This is Title",
-                                     "", true, false, "Linktext",
-                                     "http://evilbrainjono.net");
-  }
-
-  function wipeDb() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    var task = TestPilotSetup.getTaskById(getEid());
-    task.dataStore.wipeAllData();
-    var debug = document.getElementById("debug");
-    debug.innerHTML = "Wiped!";
-  }
-
-  function nukeDb() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    var task = TestPilotSetup.getTaskById(getEid());
-    task.dataStore.nukeTable();
-    var debug = document.getElementById("debug");
-    debug.innerHTML = "Nuked!";
-  }
-
-  function populateFileDropdown() {
-    var codeStore = getCodeStorage();
-    if (! codeStore ) { return false }
-
-    var files = codeStore.listAllFiles();
-    var selector = document.getElementById("file-selector");
-    var opt, i;
-    for (var i = 0; i < files.length; i++) {
-      opt = document.createElement("option");
-      opt.innerHTML = files[i];
-      selector.appendChild(opt);
-    }
-
-    selector = document.getElementById("task-selector");
-    var tasks = TestPilotSetup.getAllTasks();
-    var title;
-    for (i = 0; i < tasks.length; i++) {
-      opt = document.createElement("option");
-      title = tasks[i].title;
-      opt.innerHTML = title;
-      opt.setAttribute("value", tasks[i].id);
-      selector.appendChild(opt);
-    }
-    return true;
-  }
-
-  function showSelectedTaskStatus() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    var task = TestPilotSetup.getTaskById(getEid());
-    document.getElementById("show-status-span").innerHTML = task.status;
-    var selector = document.getElementById("status-selector");
-    selector.selectedIndex = task.status;
-  }
-
-  function resetSelectedTask() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    var task = TestPilotSetup.getTaskById(getEid());
-    task.changeStatus(0, true);
-    var prefService  = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
-    var prefName= "extensions.testpilot.startDate." + task.id;
-    if (prefService.prefHasUserValue(prefName)) {
-      prefService.clearUserPref(prefName);
-    }
-    //TestPilotSetup.reloadRemoteExperiments();
-  }
-
-  function setSelectedTaskStatus() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    var task = TestPilotSetup.getTaskById(getEid());
-
-    var selector = document.getElementById("status-selector");
-    var i = selector.selectedIndex;
-    var newStatus = parseInt( selector.options[i].value );
-    task.changeStatus(newStatus, false);
-  }
-
-  function showIndexFileDropdown() {
-    var prefService  = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
-    var prefName = "extensions.testpilot.indexFileName";
-    var selector = document.getElementById("index-file-selector");
-    if (prefService.getCharPref(prefName) == "index.json") {
-      selector.selectedIndex = 0;
-    } else {
-      selector.selectedIndex = 1;
-    }
-  }
-
-  function setSelectedIndexFile() {
-    var prefService  = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
-    var prefName = "extensions.testpilot.indexFileName";
-    var selector = document.getElementById("index-file-selector");
-    var i = selector.selectedIndex;
-    prefService.setCharPref( prefName, selector.options[i].value );
-
-    // DELETE CACHED INDEX FILE
-    var file = Components.classes["@mozilla.org/file/directory_service;1"].
-                     getService(Components.interfaces.nsIProperties).
-                     get("ProfD", Components.interfaces.nsIFile);
-    file.append("TestPilotExperimentFiles");
-    file.append("index.json");
-    if (file.exists()) {
-      file.remove(false);
-    }
-  }
-
-
-   $(function(){startup()});
-
-</script>
-
-<style type="text/css">
-      canvas { border: 1px solid black; }
-    </style>
-
-</head>
-
-<body>
-<h1 id='status'><blink>loading experiments</blink></h1> <!-- take that, web standards! -->
-
-<fieldset>
-<p><select id="task-selector" onchange="showSelectedTaskStatus();"></select> Current Status = <span id="show-status-span"></span>.
-<button onclick="resetSelectedTask();showSelectedTaskStatus();">Reset Task</button>
-or set it to
-<select id="status-selector" onchange="setSelectedTaskStatus(); showSelectedTaskStatus();">
-  <option value="0">0 (New)</option>
-  <option value="1">1 (Pending)</option>
-  <option value="2">2 (Starting)</option>
-  <option value="3">3 (In Progress)</option>
-  <option value="4">4 (Finished)</option>
-  <option value="5">5 (Cancelled)</option>
-  <option value="6">6 (Submitted)</option>
-  <option value="7">7 (Results)</option>
-  <option value="8">8 (Archived)</option>
-</select>
-<button onclick="wipeDb();">Wipe My Data</button>
-<button onclick="nukeDb();">NUKE</button>
-<button onclick="uploadData();">Upload My Data</button>
-<button onclick="showMetaData();">Show Metadata</button>
-<button onclick="runUnitTests();">Run Tests</button>
-</fieldset>
-<fieldset>
-<p><button onclick="makeThereBeAPopup();">Show Dummy Popup</button>
-<button onclick="reloadAllExperiments();">Reload All Experiments</button>
-<button onclick="remindMe();">Notify Me</button>
-<button onclick="testJarStore();">Test Jar Store</button>
-Index file:
-<select id="index-file-selector" onchange="setSelectedIndexFile();">
-  <option value="index.json">index.json</option>
-  <option value="index-dev.json">index-dev.json</option>
-</select>
-</p>
-</fieldset>
-<p><span id="debug"></span></p>
-
-
-<textarea id="experiment-code-area" rows="40" cols="80">
-</textarea>
-<select id="file-selector"></select>
-<button onclick="loadExperimentCode();">Load Ye Code</button>
-<button onclick="saveAndRun();">Save And Run Ye Code</button>
-
-
-</body> </html>
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/experiment-page.js
+++ /dev/null
@@ -1,428 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-const PAGE_TYPE_STATUS = 0;
-const PAGE_TYPE_QUIT = 1;
-var stringBundle;
-
-  function showRawData(experimentId) {
-    window.openDialog(
-      "chrome://testpilot/content/raw-data-dialog.xul",
-      "TestPilotRawDataDialog", "chrome,centerscreen,resizable,scrollbars",
-      experimentId);
-  }
-
-  function getUrlParam(name) {
-    // from http://www.netlobo.com/url_query_string_javascript.html
-    name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
-    var regexS = "[\\?&]"+name+"=([^&#]*)";
-    var regex = new RegExp(regexS);
-    var results = regex.exec(window.location.href);
-    if( results == null )
-      return "";
-    else
-      return results[1];
-  }
-
-  function uploadData() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    let eid = getUrlParam("eid");
-    let task = TestPilotSetup.getTaskById(eid);
-
-    // If always-submit-checkbox is checked, set the pref
-    if (task._recursAutomatically) {
-      let checkBox = document.getElementById("always-submit-checkbox");
-      if (checkBox && checkBox.checked) {
-        task.setRecurPref(TaskConstants.ALWAYS_SUBMIT);
-      }
-    }
-
-    // Study web content must provide an element with id 'upload-status'.
-    // Fill it first with a message about data being uploaded; if there's
-    // an error, replace it with the error message.
-    let uploadStatus = document.getElementById("upload-status");
-    uploadStatus.innerHTML =
-      stringBundle.GetStringFromName("testpilot.statusPage.uploadingData");
-    task.upload( function(success) {
-      if (success) {
-        window.location =
-	  "chrome://testpilot/content/status.html?eid=" + eid;
-      } else {
-        // Replace 'now uploading' message
-        let errorParagraph = document.createElement("p");
-        errorParagraph.innerHTML = stringBundle.GetStringFromName("testpilot.statusPage.uploadErrorMsg");
-        let willRetryParagraph = document.createElement("p");
-        willRetryParagraph.innerHTML = stringBundle.GetStringFromName("testpilot.statusPage.willRetry");
-        uploadStatus.innerHTML = "";
-        uploadStatus.appendChild(errorParagraph);
-        uploadStatus.appendChild(willRetryParagraph);
-      }
-    });
-  }
-
-  function deleteData() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    Components.utils.import("resource://testpilot/modules/tasks.js");
-    let eid = getUrlParam("eid");
-    let task = TestPilotSetup.getTaskById(eid);
-    task.dataStore.wipeAllData();
-    // reload the URL after wiping all data.
-    window.location = "chrome://testpilot/content/status.html?eid=" + eid;
-  }
-
-  function saveCanvas(canvas) {
-    const nsIFilePicker = Components.interfaces.nsIFilePicker;
-    let fp = Components.classes["@mozilla.org/filepicker;1"].
-             createInstance(nsIFilePicker);
-    let fpCallback = function fpCallback_done(aResult) {
-      if (aResult == nsIFilePicker.returnOK ||
-          aResult == nsIFilePicker.returnReplace) {
-        const nsIWebBrowserPersist =
-          Components.interfaces.nsIWebBrowserPersist;
-        let file = fp.file;
-
-        // create a data url from the canvas and then create URIs of the
-        // source and targets
-        let io = Components.classes["@mozilla.org/network/io-service;1"].
-                 getService(Components.interfaces.nsIIOService);
-        let source = io.newURI(canvas.toDataURL("image/png"), "UTF8", null);
-        let target = io.newFileURI(file);
-
-        // prepare to save the canvas data
-        let persist = Components.classes[
-          "@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].
-          createInstance(nsIWebBrowserPersist);
-        persist.persistFlags = nsIWebBrowserPersist.
-          PERSIST_FLAGS_REPLACE_EXISTING_FILES;
-        persist.persistFlags |= nsIWebBrowserPersist.
-          PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
-
-        // displays a download dialog (remove these 3 lines for silent download)
-        let xfer = Components.classes["@mozilla.org/transfer;1"].
-                   createInstance(Components.interfaces.nsITransfer);
-        xfer.init(source, target, "", null, null, null, persist, false);
-        persist.progressListener = xfer;
-
-        // save the canvas data to the file
-        persist.saveURI(source, null, null, null, null, file, null);
-      }
-    };
-
-    fp.init(window, null, nsIFilePicker.modeSave);
-    fp.appendFilters(nsIFilePicker.filterImages | nsIFilePicker.filterAll);
-    fp.defaultString = "canvas.png";
-    fp.open(fpCallback);
-  }
-
-  function exportData() {
-    const nsIFilePicker = Components.interfaces.nsIFilePicker;
-    let eid = getUrlParam("eid");
-    let task = TestPilotSetup.getTaskById(eid);
-    let fp = Components.classes["@mozilla.org/filepicker;1"].
-             createInstance(nsIFilePicker);
-    let fpCallback = function fpCallback_done(aResult) {
-      if (aResult == nsIFilePicker.returnOK ||
-          aResult == nsIFilePicker.returnReplace) {
-        const nsIWebBrowserPersist =
-          Components.interfaces.nsIWebBrowserPersist;
-        let foStream =
-          Components.classes["@mozilla.org/network/file-output-stream;1"].
-          createInstance(Components.interfaces.nsIFileOutputStream);
-        let converter =
-          Components.classes["@mozilla.org/intl/converter-output-stream;1"].
-          createInstance(Components.interfaces.nsIConverterOutputStream);
-        let file = fp.file;
-        let dataStore = task.dataStore;
-        let columnNames = dataStore.getHumanReadableColumnNames();
-        let propertyNames = dataStore.getPropertyNames();
-        let csvString = "";
-
-        // titles
-        for (let i = 0; i < columnNames.length; i++) {
-          csvString += "\"" + columnNames[i] + "\",";
-        }
-        if (csvString.length > 0) {
-          csvString = csvString.substring(0, (csvString.length - 1));
-          csvString += "\n";
-        }
-
-        dataStore.getAllDataAsJSON(true, function(rawData) {
-          // data
-          for (let i = 0; i < rawData.length; i++) {
-            for (let j = 0; j < columnNames.length; j++) {
-              csvString += "\"" + rawData[i][propertyNames[j]] + "\",";
-            }
-            csvString = csvString.substring(0, (csvString.length - 1));
-            csvString += "\n";
-          }
-
-          // write, create, truncate
-          foStream.init(file, 0x02 | 0x08 | 0x20, parseInt("0664", 8), 0);
-          converter.init(foStream, "UTF-8", 0, 0);
-          converter.writeString(csvString);
-          converter.close();
-        });
-      }
-    };
-
-    fp.init(window, null, nsIFilePicker.modeSave);
-    fp.appendFilters(nsIFilePicker.filterImages | nsIFilePicker.filterAll);
-    fp.defaultString = task.title + ".csv";
-    fp.open(fpCallback);
-  }
-
-  function openLink(url) {
-    // open the link in the chromeless window
-    let wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
-                       .getService(Components.interfaces.nsIWindowMediator);
-    let recentWindow = wm.getMostRecentWindow("navigator:browser");
-
-    if (recentWindow) {
-      recentWindow.TestPilotWindowUtils.openInTab(url);
-    } else {
-      window.open(url);
-    }
-  }
-
-  function getTestEndingDate(experimentId) {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    var task = TestPilotSetup.getTaskById(experimentId);
-    var endDate = new Date(task.endDate);
-    var diff = (endDate - Date.now());
-    var span = document.getElementById("test-end-time");
-    if (!span) {
-      return;
-    }
-    if (diff < 0) {
-      span.innerHTML =
-        stringBundle.GetStringFromName("testpilot.statusPage.endedAlready");
-      return;
-    }
-    var hours = diff / (60 * 60 * 1000);
-    if (hours < 24) {
-      span.innerHTML =
-        stringBundle.formatStringFromName(
-	  "testpilot.statusPage.todayAt", [endDate.toLocaleTimeString()], 1);
-    } else {
-      span.innerHTML =
-        stringBundle.formatStringFromName(
-	  "testpilot.statusPage.endOn", [endDate.toLocaleString()], 1);
-    }
-  }
-
-  function showMetaData() {
-    Components.utils.import("resource://testpilot/modules/metadata.js");
-    Components.utils.import("resource://gre/modules/PluralForm.jsm");
-    MetadataCollector.getMetadata(function(md) {
-      var mdLocale = document.getElementById("md-locale");
-      if (mdLocale)
-        mdLocale.innerHTML = md.location;
-      var mdVersion = document.getElementById("md-version");
-      if (mdVersion)
-        mdVersion.innerHTML = md.version;
-      var mdOs = document.getElementById("md-os");
-      if (mdOs)
-        mdOs.innerHTML = md.operatingSystem;
-      var mdNumExt = document.getElementById("md-num-ext");
-      if (mdNumExt) {
-        // This computes the correctly localized singular or plural string
-        // of the number of extensions, e.g. "1 extension", "2 extensions", etc.
-        let str = stringBundle.GetStringFromName("testpilot.statusPage.numExtensions");
-        var numExt = md.extensions.length;
-        mdNumExt.innerHTML = PluralForm.get(numExt, str).replace("#1", numExt);
-      }
-    });
-  }
-
-  function onQuitPageLoad() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    setStrings(PAGE_TYPE_QUIT);
-    let eid = getUrlParam("eid");
-    let task = TestPilotSetup.getTaskById(eid);
-    let header = document.getElementById("about-quit-title");
-    header.innerHTML =
-      stringBundle.formatStringFromName(
-	"testpilot.quitPage.aboutToQuit", [task.title], 1);
-
-    if (task._recursAutomatically) {
-      document.getElementById("recur-options").setAttribute("style", "");
-      document.getElementById("recur-checkbox-container").
-        setAttribute("style", "");
-    }
-  }
-
-  function quitExperiment() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    Components.utils.import("resource://testpilot/modules/tasks.js");
-    let eid = getUrlParam("eid");
-    let reason = document.getElementById("reason-for-quit").value;
-    let task = TestPilotSetup.getTaskById(eid);
-    task.optOut(reason, function(success) {
-      // load the you-are-canceleed page.
-      window.location = "chrome://testpilot/content/status.html?eid=" + eid;
-    });
-
-    // If opt-out-forever checkbox is checked, opt out forever!
-    if (task._recursAutomatically) {
-      let checkBox = document.getElementById("opt-out-forever");
-      if (checkBox.checked) {
-        task.setRecurPref(TaskConstants.NEVER_SUBMIT);
-      }
-      // quit test so rescheduling
-      task._reschedule();
-    }
-  }
-
-  function updateRecurSettings() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    let eid = getUrlParam("eid");
-    let experiment = TestPilotSetup.getTaskById(eid);
-    let recurSelector = document.getElementById("recur-selector");
-    let newValue = recurSelector.options[recurSelector.selectedIndex].value;
-    experiment.setRecurPref(parseInt(newValue));
-  }
-
-  function showRecurControls(experiment) {
-    Components.utils.import("resource://testpilot/modules/tasks.js");
-    let recurPrefSpan = document.getElementById("recur-pref");
-    if (!recurPrefSpan) {
-      return;
-    }
-    let days = experiment._recurrenceInterval;
-    recurPrefSpan.innerHTML =
-      stringBundle.formatStringFromName(
-	"testpilot.statusPage.recursEveryNumberOfDays", [days], 1);
-
-    let controls = document.getElementById("recur-controls");
-    let selector = document.createElement("select");
-    controls.appendChild(selector);
-    selector.setAttribute("onchange", "updateRecurSettings();");
-    selector.setAttribute("id", "recur-selector");
-
-    let option = document.createElement("option");
-    option.setAttribute("value", TaskConstants.ASK_EACH_TIME);
-    if (experiment.recurPref == TaskConstants.ASK_EACH_TIME) {
-      option.setAttribute("selected", "true");
-    }
-    option.innerHTML =
-      stringBundle.GetStringFromName(
-	"testpilot.statusPage.askMeBeforeSubmitData");
-    selector.appendChild(option);
-
-    option = document.createElement("option");
-    option.setAttribute("value", TaskConstants.ALWAYS_SUBMIT);
-    if (experiment.recurPref == TaskConstants.ALWAYS_SUBMIT) {
-      option.setAttribute("selected", "true");
-    }
-    option.innerHTML =
-      stringBundle.GetStringFromName(
-	"testpilot.statusPage.alwaysSubmitData");
-    selector.appendChild(option);
-
-    option = document.createElement("option");
-    option.setAttribute("value", TaskConstants.NEVER_SUBMIT);
-    if (experiment.recurPref == TaskConstants.NEVER_SUBMIT) {
-      option.setAttribute("selected", "true");
-    }
-    option.innerHTML =
-      stringBundle.GetStringFromName(
-	"testpilot.statusPage.neverSubmitData");
-    selector.appendChild(option);
-  }
-
-  function loadExperimentPage() {
-    Components.utils.import("resource://testpilot/modules/setup.js");
-    Components.utils.import("resource://testpilot/modules/tasks.js");
-    var contentDiv = document.getElementById("experiment-specific-text");
-    var dataPrivacyDiv = document.getElementById("data-privacy-text");
-    // Get experimentID from the GET args of page
-    var eid = getUrlParam("eid");
-    var experiment = TestPilotSetup.getTaskById(eid);
-    if (!experiment) {
-      // Possible that experiments aren't done loading yet.  Try again in
-      // a few seconds.
-      contentDiv.innerHTML =
-        stringBundle.GetStringFromName("testpilot.statusPage.loading");
-      window.setTimeout(function() { loadExperimentPage(); }, 2000);
-      return;
-    }
-
-    // Let the experiment fill in its web content (asynchronous)
-    experiment.getWebContent(function(webContent) {
-      contentDiv.innerHTML = webContent;
-
-      // Metadata and start/end date should be filled in for every experiment:
-      showMetaData();
-      getTestEndingDate(eid);
-      if (experiment._recursAutomatically &&
-        experiment.status != TaskConstants.STATUS_FINISHED) {
-        showRecurControls(experiment);
-      }
-
-      // Do whatever the experiment's web content wants done on load
-      // (Usually drawing a graph) - must be done after innerHTML is set.
-      experiment.webContent.onPageLoad(experiment, document, jQuery);
-    });
-
-    experiment.getDataPrivacyContent(function(dataPrivacyContent) {
-      if (dataPrivacyContent && dataPrivacyContent.length > 0) {
-        dataPrivacyDiv.innerHTML = dataPrivacyContent;
-        dataPrivacyDiv.removeAttribute("hidden");
-      }
-    });
-  }
-
-  function onStatusPageLoad() {
-    setStrings(PAGE_TYPE_STATUS);
-    /* An experiment ID (eid) must be provided in the url params. Show status
-     * for that experiment.*/
-    loadExperimentPage();
-  }
-
-  function setStrings(pageType) {
-    stringBundle =
-      Components.classes["@mozilla.org/intl/stringbundle;1"].
-        getService(Components.interfaces.nsIStringBundleService).
-	  createBundle("chrome://testpilot/locale/main.properties");
-    let map;
-    let mapLength;
-
-    if (pageType == PAGE_TYPE_STATUS) {
-      map = [
-	{ id: "page-title", stringKey: "testpilot.fullBrandName" },
-	{ id: "comments-and-discussions-link",
-	  stringKey: "testpilot.page.commentsAndDiscussions" },
-	{ id: "propose-test-link",
-	  stringKey: "testpilot.page.proposeATest" },
-	{ id: "testpilot-twitter-link",
-	  stringKey: "testpilot.page.testpilotOnTwitter" }
-      ];
-    } else if (pageType == PAGE_TYPE_QUIT) {
-      map = [
-	{ id: "page-title", stringKey: "testpilot.fullBrandName" },
-	{ id: "comments-and-discussions-link",
-	  stringKey: "testpilot.page.commentsAndDiscussions" },
-	{ id: "propose-test-link",
-	  stringKey: "testpilot.page.proposeATest" },
-	{ id: "testpilot-twitter-link",
-	  stringKey: "testpilot.page.testpilotOnTwitter" },
-	{ id: "optional-message",
-	  stringKey: "testpilot.quitPage.optionalMessage" },
-	{ id: "reason-text",
-	  stringKey: "testpilot.quitPage.reason" },
-	{ id: "recur-options",
-	  stringKey: "testpilot.quitPage.recurringStudy" },
-	{ id: "quit-forever-text",
-	  stringKey: "testpilot.quitPage.quitForever" },
-	{ id: "quit-study-link",
-	  stringKey: "testpilot.quitPage.quitStudy" }
-      ];
-    }
-    mapLength = map.length;
-    for (let i = 0; i < mapLength; i++) {
-      let entry = map[i];
-      document.getElementById(entry.id).innerHTML =
-        stringBundle.GetStringFromName(entry.stringKey);
-    }
-  }
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/feedback-browser.xul
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0"?>
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE overlay [
-  <!ENTITY % testpilotDTD SYSTEM "chrome://testpilot/locale/main.dtd">
-    %testpilotDTD;
-]>
-
-<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-<menupopup id="menu_ToolsPopup">
-  <menu id="pilot-menu" insertafter="menu_openAddons" />
-</menupopup>
-
-<toolbar id="nav-bar">
-  <panel id="pilot-notification-popup" hidden="true" noautofocus="true"
-    level="parent" position="after_start">
-    <vbox class="pilot-notification-popup-container">
-      <hbox class="pilot-notification-toprow">
-        <image id="pilot-notification-icon" />
-        <vbox pack="center">
-          <label id="pilot-notification-title" class="pilot-title" />
-        </vbox>
-        <spacer flex="1" />
-        <vbox pack="start">
-          <image id="pilot-notification-close"
-            tooltiptext="&testpilot.notification.close.tooltip;" />
-        </vbox>
-      </hbox>
-      <description id="pilot-notification-text" />
-      <hbox align="right"><label id="pilot-notification-link" /></hbox>
-      <hbox>
-        <checkbox id="pilot-notification-always-submit-checkbox"
-          label="&testpilot.settings.alwaysSubmitData.label;" />
-        <spacer flex="1" />
-      </hbox>
-      <hbox align="right">
-        <button id="pilot-notification-submit" />
-      </hbox>
-    </vbox>
-  </panel>
-</toolbar>
-
-<menu id="pilot-menu" class="menu-iconic"
-      label="&testpilot.feedbackbutton.label;"
-      insertafter="addonsManager">
-  <menupopup id="pilot-menu-popup"
-             onpopupshowing="TestPilotMenuUtils.onPopupShowing(event);"
-             onpopuphiding="TestPilotMenuUtils.onPopupHiding(event);">
-    <menuitem id="feedback-menu-happy-button"
-              class="menuitem-iconic"
-              image="chrome://testpilot-os/skin/feedback-smile-16x16.png"
-              label = "&testpilot.happy.label;"
-              oncommand="TestPilotWindowUtils.openFeedbackPage('happy');"/>
-    <menuitem id="feedback-menu-sad-button"
-              class="menuitem-iconic"
-              image="chrome://testpilot-os/skin/feedback-frown-16x16.png"
-              label = "&testpilot.sad.label;"
-              oncommand="TestPilotWindowUtils.openFeedbackPage('sad');"/>
-    <menuseparator/>
-    <menuitem id="feedback-menu-show-studies"
-              label="&testpilot.allYourStudies.label;"
-              oncommand="TestPilotWindowUtils.openAllStudiesWindow();"/>
-    <menuitem id="feedback-menu-enable-studies" 
-              label="&testpilot.enable.label;"
-              oncommand="TestPilotMenuUtils.togglePref('runStudies');"/>
-  </menupopup>
-</menu>
-</overlay>
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.colorhelpers.js
+++ /dev/null
@@ -1,174 +0,0 @@
-/* Plugin for jQuery for working with colors.
- * 
- * Version 1.0.
- * 
- * Inspiration from jQuery color animation plugin by John Resig.
- *
- * Released under the MIT license by Ole Laursen, October 2009.
- *
- * Examples:
- *
- *   $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
- *   var c = $.color.extract($("#mydiv"), 'background-color');
- *   console.log(c.r, c.g, c.b, c.a);
- *   $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
- *
- * Note that .scale() and .add() work in-place instead of returning
- * new objects.
- */ 
-
-(function() {
-    jQuery.color = {};
-
-    // construct color object with some convenient chainable helpers
-    jQuery.color.make = function (r, g, b, a) {
-        var o = {};
-        o.r = r || 0;
-        o.g = g || 0;
-        o.b = b || 0;
-        o.a = a != null ? a : 1;
-
-        o.add = function (c, d) {
-            for (var i = 0; i < c.length; ++i)
-                o[c.charAt(i)] += d;
-            return o.normalize();
-        };
-        
-        o.scale = function (c, f) {
-            for (var i = 0; i < c.length; ++i)
-                o[c.charAt(i)] *= f;
-            return o.normalize();
-        };
-        
-        o.toString = function () {
-            if (o.a >= 1.0) {
-                return "rgb("+[o.r, o.g, o.b].join(",")+")";
-            } else {
-                return "rgba("+[o.r, o.g, o.b, o.a].join(",")+")";
-            }
-        };
-
-        o.normalize = function () {
-            function clamp(min, value, max) {
-                return value < min ? min: (value > max ? max: value);
-            }
-            
-            o.r = clamp(0, parseInt(o.r), 255);
-            o.g = clamp(0, parseInt(o.g), 255);
-            o.b = clamp(0, parseInt(o.b), 255);
-            o.a = clamp(0, o.a, 1);
-            return o;
-        };
-
-        o.clone = function () {
-            return jQuery.color.make(o.r, o.b, o.g, o.a);
-        };
-
-        return o.normalize();
-    }
-
-    // extract CSS color property from element, going up in the DOM
-    // if it's "transparent"
-    jQuery.color.extract = function (elem, css) {
-        var c;
-        do {
-            c = elem.css(css).toLowerCase();
-            // keep going until we find an element that has color, or
-            // we hit the body
-            if (c != '' && c != 'transparent')
-                break;
-            elem = elem.parent();
-        } while (!jQuery.nodeName(elem.get(0), "body"));
-
-        // catch Safari's way of signalling transparent
-        if (c == "rgba(0, 0, 0, 0)")
-            c = "transparent";
-        
-        return jQuery.color.parse(c);
-    }
-    
-    // parse CSS color string (like "rgb(10, 32, 43)" or "#fff"),
-    // returns color object
-    jQuery.color.parse = function (str) {
-        var res, m = jQuery.color.make;
-
-        // Look for rgb(num,num,num)
-        if (res = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))
-            return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10));
-        
-        // Look for rgba(num,num,num,num)
-        if (res = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
-            return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10), parseFloat(res[4]));
-            
-        // Look for rgb(num%,num%,num%)
-        if (res = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))
-            return m(parseFloat(res[1])*2.55, parseFloat(res[2])*2.55, parseFloat(res[3])*2.55);
-
-        // Look for rgba(num%,num%,num%,num)
-        if (res = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
-            return m(parseFloat(res[1])*2.55, parseFloat(res[2])*2.55, parseFloat(res[3])*2.55, parseFloat(res[4]));
-        
-        // Look for #a0b1c2
-        if (res = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))
-            return m(parseInt(res[1], 16), parseInt(res[2], 16), parseInt(res[3], 16));
-
-        // Look for #fff
-        if (res = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))
-            return m(parseInt(res[1]+res[1], 16), parseInt(res[2]+res[2], 16), parseInt(res[3]+res[3], 16));
-
-        // Otherwise, we're most likely dealing with a named color
-        var name = jQuery.trim(str).toLowerCase();
-        if (name == "transparent")
-            return m(255, 255, 255, 0);
-        else {
-            res = lookupColors[name];
-            return m(res[0], res[1], res[2]);
-        }
-    }
-    
-    var lookupColors = {
-        aqua:[0,255,255],
-        azure:[240,255,255],
-        beige:[245,245,220],
-        black:[0,0,0],
-        blue:[0,0,255],
-        brown:[165,42,42],
-        cyan:[0,255,255],
-        darkblue:[0,0,139],
-        darkcyan:[0,139,139],
-        darkgrey:[169,169,169],
-        darkgreen:[0,100,0],
-        darkkhaki:[189,183,107],
-        darkmagenta:[139,0,139],
-        darkolivegreen:[85,107,47],
-        darkorange:[255,140,0],
-        darkorchid:[153,50,204],
-        darkred:[139,0,0],
-        darksalmon:[233,150,122],
-        darkviolet:[148,0,211],
-        fuchsia:[255,0,255],
-        gold:[255,215,0],
-        green:[0,128,0],
-        indigo:[75,0,130],
-        khaki:[240,230,140],
-        lightblue:[173,216,230],
-        lightcyan:[224,255,255],
-        lightgreen:[144,238,144],
-        lightgrey:[211,211,211],
-        lightpink:[255,182,193],
-        lightyellow:[255,255,224],
-        lime:[0,255,0],
-        magenta:[255,0,255],
-        maroon:[128,0,0],
-        navy:[0,0,128],
-        olive:[128,128,0],
-        orange:[255,165,0],
-        pink:[255,192,203],
-        purple:[128,0,128],
-        violet:[128,0,128],
-        red:[255,0,0],
-        silver:[192,192,192],
-        white:[255,255,255],
-        yellow:[255,255,0]
-    };    
-})();
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.colorhelpers.min.js
+++ /dev/null
@@ -1,1 +0,0 @@
-(function(){jQuery.color={};jQuery.color.make=function(E,D,B,C){var F={};F.r=E||0;F.g=D||0;F.b=B||0;F.a=C!=null?C:1;F.add=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]+=H}return F.normalize()};F.scale=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]*=H}return F.normalize()};F.toString=function(){if(F.a>=1){return"rgb("+[F.r,F.g,F.b].join(",")+")"}else{return"rgba("+[F.r,F.g,F.b,F.a].join(",")+")"}};F.normalize=function(){function G(I,J,H){return J<I?I:(J>H?H:J)}F.r=G(0,parseInt(F.r),255);F.g=G(0,parseInt(F.g),255);F.b=G(0,parseInt(F.b),255);F.a=G(0,F.a,1);return F};F.clone=function(){return jQuery.color.make(F.r,F.b,F.g,F.a)};return F.normalize()};jQuery.color.extract=function(C,B){var D;do{D=C.css(B).toLowerCase();if(D!=""&&D!="transparent"){break}C=C.parent()}while(!jQuery.nodeName(C.get(0),"body"));if(D=="rgba(0, 0, 0, 0)"){D="transparent"}return jQuery.color.parse(D)};jQuery.color.parse=function(E){var D,B=jQuery.color.make;if(D=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10))}if(D=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10),parseFloat(D[4]))}if(D=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55)}if(D=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55,parseFloat(D[4]))}if(D=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(E)){return B(parseInt(D[1],16),parseInt(D[2],16),parseInt(D[3],16))}if(D=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(E)){return B(parseInt(D[1]+D[1],16),parseInt(D[2]+D[2],16),parseInt(D[3]+D[3],16))}var C=jQuery.trim(E).toLowerCase();if(C=="transparent"){return B(255,255,255,0)}else{D=A[C];return B(D[0],D[1],D[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.crosshair.js
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-Flot plugin for showing a crosshair, thin lines, when the mouse hovers
-over the plot.
-
-  crosshair: {
-    mode: null or "x" or "y" or "xy"
-    color: color
-    lineWidth: number
-  }
-
-Set the mode to one of "x", "y" or "xy". The "x" mode enables a
-vertical crosshair that lets you trace the values on the x axis, "y"
-enables a horizontal crosshair and "xy" enables them both. "color" is
-the color of the crosshair (default is "rgba(170, 0, 0, 0.80)"),
-"lineWidth" is the width of the drawn lines (default is 1).
-
-The plugin also adds four public methods:
-
-  - setCrosshair(pos)
-
-    Set the position of the crosshair. Note that this is cleared if
-    the user moves the mouse. "pos" should be on the form { x: xpos,
-    y: ypos } (or x2 and y2 if you're using the secondary axes), which
-    is coincidentally the same format as what you get from a "plothover"
-    event. If "pos" is null, the crosshair is cleared.
-
-  - clearCrosshair()
-
-    Clear the crosshair.
-
-  - lockCrosshair(pos)
-
-    Cause the crosshair to lock to the current location, no longer
-    updating if the user moves the mouse. Optionally supply a position
-    (passed on to setCrosshair()) to move it to.
-
-    Example usage:
-      var myFlot = $.plot( $("#graph"), ..., { crosshair: { mode: "x" } } };
-      $("#graph").bind("plothover", function (evt, position, item) {
-        if (item) {
-          // Lock the crosshair to the data point being hovered
-          myFlot.lockCrosshair({ x: item.datapoint[0], y: item.datapoint[1] });
-        }
-        else {
-          // Return normal crosshair operation
-          myFlot.unlockCrosshair();
-        }
-      });
-
-  - unlockCrosshair()
-
-    Free the crosshair to move again after locking it.
-*/
-
-(function ($) {
-    var options = {
-        crosshair: {
-            mode: null, // one of null, "x", "y" or "xy",
-            color: "rgba(170, 0, 0, 0.80)",
-            lineWidth: 1
-        }
-    };
-    
-    function init(plot) {
-        // position of crosshair in pixels
-        var crosshair = { x: -1, y: -1, locked: false };
-
-        plot.setCrosshair = function setCrosshair(pos) {
-            if (!pos)
-                crosshair.x = -1;
-            else {
-                var axes = plot.getAxes();
-                
-                crosshair.x = Math.max(0, Math.min(pos.x != null ? axes.xaxis.p2c(pos.x) : axes.x2axis.p2c(pos.x2), plot.width()));
-                crosshair.y = Math.max(0, Math.min(pos.y != null ? axes.yaxis.p2c(pos.y) : axes.y2axis.p2c(pos.y2), plot.height()));
-            }
-            
-            plot.triggerRedrawOverlay();
-        };
-        
-        plot.clearCrosshair = plot.setCrosshair; // passes null for pos
-        
-        plot.lockCrosshair = function lockCrosshair(pos) {
-            if (pos)
-                plot.setCrosshair(pos);
-            crosshair.locked = true;
-        }
-
-        plot.unlockCrosshair = function unlockCrosshair() {
-            crosshair.locked = false;
-        }
-
-        plot.hooks.bindEvents.push(function (plot, eventHolder) {
-            if (!plot.getOptions().crosshair.mode)
-                return;
-
-            eventHolder.mouseout(function () {
-                if (crosshair.x != -1) {
-                    crosshair.x = -1;
-                    plot.triggerRedrawOverlay();
-                }
-            });
-            
-            eventHolder.mousemove(function (e) {
-                if (plot.getSelection && plot.getSelection()) {
-                    crosshair.x = -1; // hide the crosshair while selecting
-                    return;
-                }
-                
-                if (crosshair.locked)
-                    return;
-                
-                var offset = plot.offset();
-                crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
-                crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
-                plot.triggerRedrawOverlay();
-            });
-        });
-
-        plot.hooks.drawOverlay.push(function (plot, ctx) {
-            var c = plot.getOptions().crosshair;
-            if (!c.mode)
-                return;
-
-            var plotOffset = plot.getPlotOffset();
-            
-            ctx.save();
-            ctx.translate(plotOffset.left, plotOffset.top);
-
-            if (crosshair.x != -1) {
-                ctx.strokeStyle = c.color;
-                ctx.lineWidth = c.lineWidth;
-                ctx.lineJoin = "round";
-
-                ctx.beginPath();
-                if (c.mode.indexOf("x") != -1) {
-                    ctx.moveTo(crosshair.x, 0);
-                    ctx.lineTo(crosshair.x, plot.height());
-                }
-                if (c.mode.indexOf("y") != -1) {
-                    ctx.moveTo(0, crosshair.y);
-                    ctx.lineTo(plot.width(), crosshair.y);
-                }
-                ctx.stroke();
-            }
-            ctx.restore();
-        });
-    }
-    
-    $.plot.plugins.push({
-        init: init,
-        options: options,
-        name: 'crosshair',
-        version: '1.0'
-    });
-})(jQuery);
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.crosshair.min.js
+++ /dev/null
@@ -1,1 +0,0 @@
-(function(B){var A={crosshair:{mode:null,color:"rgba(170, 0, 0, 0.80)",lineWidth:1}};function C(G){var H={x:-1,y:-1,locked:false};G.setCrosshair=function D(J){if(!J){H.x=-1}else{var I=G.getAxes();H.x=Math.max(0,Math.min(J.x!=null?I.xaxis.p2c(J.x):I.x2axis.p2c(J.x2),G.width()));H.y=Math.max(0,Math.min(J.y!=null?I.yaxis.p2c(J.y):I.y2axis.p2c(J.y2),G.height()))}G.triggerRedrawOverlay()};G.clearCrosshair=G.setCrosshair;G.lockCrosshair=function E(I){if(I){G.setCrosshair(I)}H.locked=true};G.unlockCrosshair=function F(){H.locked=false};G.hooks.bindEvents.push(function(J,I){if(!J.getOptions().crosshair.mode){return }I.mouseout(function(){if(H.x!=-1){H.x=-1;J.triggerRedrawOverlay()}});I.mousemove(function(K){if(J.getSelection&&J.getSelection()){H.x=-1;return }if(H.locked){return }var L=J.offset();H.x=Math.max(0,Math.min(K.pageX-L.left,J.width()));H.y=Math.max(0,Math.min(K.pageY-L.top,J.height()));J.triggerRedrawOverlay()})});G.hooks.drawOverlay.push(function(K,I){var L=K.getOptions().crosshair;if(!L.mode){return }var J=K.getPlotOffset();I.save();I.translate(J.left,J.top);if(H.x!=-1){I.strokeStyle=L.color;I.lineWidth=L.lineWidth;I.lineJoin="round";I.beginPath();if(L.mode.indexOf("x")!=-1){I.moveTo(H.x,0);I.lineTo(H.x,K.height())}if(L.mode.indexOf("y")!=-1){I.moveTo(0,H.y);I.lineTo(K.width(),H.y)}I.stroke()}I.restore()})}B.plot.plugins.push({init:C,options:A,name:"crosshair",version:"1.0"})})(jQuery);
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.image.js
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
-Flot plugin for plotting images, e.g. useful for putting ticks on a
-prerendered complex visualization.
-
-The data syntax is [[image, x1, y1, x2, y2], ...] where (x1, y1) and
-(x2, y2) are where you intend the two opposite corners of the image to
-end up in the plot. Image must be a fully loaded Javascript image (you
-can make one with new Image()). If the image is not complete, it's
-skipped when plotting.
-
-There are two helpers included for retrieving images. The easiest work
-the way that you put in URLs instead of images in the data (like
-["myimage.png", 0, 0, 10, 10]), then call $.plot.image.loadData(data,
-options, callback) where data and options are the same as you pass in
-to $.plot. This loads the images, replaces the URLs in the data with
-the corresponding images and calls "callback" when all images are
-loaded (or failed loading). In the callback, you can then call $.plot
-with the data set. See the included example.
-
-A more low-level helper, $.plot.image.load(urls, callback) is also
-included. Given a list of URLs, it calls callback with an object
-mapping from URL to Image object when all images are loaded or have
-failed loading.
-
-Options for the plugin are
-
-  series: {
-      images: {
-          show: boolean
-          anchor: "corner" or "center"
-          alpha: [0,1]
-      }
-  }
-
-which can be specified for a specific series
-
-  $.plot($("#placeholder"), [{ data: [ ... ], images: { ... } ])
-
-Note that because the data format is different from usual data points,
-you can't use images with anything else in a specific data series.
-
-Setting "anchor" to "center" causes the pixels in the image to be
-anchored at the corner pixel centers inside of at the pixel corners,
-effectively letting half a pixel stick out to each side in the plot.
-
-
-A possible future direction could be support for tiling for large
-images (like Google Maps).
-
-*/
-
-(function ($) {
-    var options = {
-        series: {
-            images: {
-                show: false,
-                alpha: 1,
-                anchor: "corner" // or "center"
-            }
-        }
-    };
-
-    $.plot.image = {};
-
-    $.plot.image.loadDataImages = function (series, options, callback) {
-        var urls = [], points = [];
-
-        var defaultShow = options.series.images.show;
-        
-        $.each(series, function (i, s) {
-            if (!(defaultShow || s.images.show))
-                return;
-            
-            if (s.data)
-                s = s.data;
-
-            $.each(s, function (i, p) {
-                if (typeof p[0] == "string") {
-                    urls.push(p[0]);
-                    points.push(p);
-                }
-            });
-        });
-
-        $.plot.image.load(urls, function (loadedImages) {
-            $.each(points, function (i, p) {
-                var url = p[0];
-                if (loadedImages[url])
-                    p[0] = loadedImages[url];
-            });
-
-            callback();
-        });
-    }
-    
-    $.plot.image.load = function (urls, callback) {
-        var missing = urls.length, loaded = {};
-        if (missing == 0)
-            callback({});
-
-        $.each(urls, function (i, url) {
-            var handler = function () {
-                --missing;
-                
-                loaded[url] = this;
-                
-                if (missing == 0)
-                    callback(loaded);
-            };
-
-            $('<img />').load(handler).error(handler).attr('src', url);
-        });
-    }
-    
-    function draw(plot, ctx) {
-        var plotOffset = plot.getPlotOffset();
-        
-        $.each(plot.getData(), function (i, series) {
-            var points = series.datapoints.points,
-                ps = series.datapoints.pointsize;
-            
-            for (var i = 0; i < points.length; i += ps) {
-                var img = points[i],
-                    x1 = points[i + 1], y1 = points[i + 2],
-                    x2 = points[i + 3], y2 = points[i + 4],
-                    xaxis = series.xaxis, yaxis = series.yaxis,
-                    tmp;
-
-                // actually we should check img.complete, but it
-                // appears to be a somewhat unreliable indicator in
-                // IE6 (false even after load event)
-                if (!img || img.width <= 0 || img.height <= 0)
-                    continue;
-
-                if (x1 > x2) {
-                    tmp = x2;
-                    x2 = x1;
-                    x1 = tmp;
-                }
-                if (y1 > y2) {
-                    tmp = y2;
-                    y2 = y1;
-                    y1 = tmp;
-                }
-                
-                // if the anchor is at the center of the pixel, expand the 
-                // image by 1/2 pixel in each direction
-                if (series.images.anchor == "center") {
-                    tmp = 0.5 * (x2-x1) / (img.width - 1);
-                    x1 -= tmp;
-                    x2 += tmp;
-                    tmp = 0.5 * (y2-y1) / (img.height - 1);
-                    y1 -= tmp;
-                    y2 += tmp;
-                }
-                
-                // clip
-                if (x1 == x2 || y1 == y2 ||
-                    x1 >= xaxis.max || x2 <= xaxis.min ||
-                    y1 >= yaxis.max || y2 <= yaxis.min)
-                    continue;
-
-                var sx1 = 0, sy1 = 0, sx2 = img.width, sy2 = img.height;
-                if (x1 < xaxis.min) {
-                    sx1 += (sx2 - sx1) * (xaxis.min - x1) / (x2 - x1);
-                    x1 = xaxis.min;
-                }
-
-                if (x2 > xaxis.max) {
-                    sx2 += (sx2 - sx1) * (xaxis.max - x2) / (x2 - x1);
-                    x2 = xaxis.max;
-                }
-
-                if (y1 < yaxis.min) {
-                    sy2 += (sy1 - sy2) * (yaxis.min - y1) / (y2 - y1);
-                    y1 = yaxis.min;
-                }
-
-                if (y2 > yaxis.max) {
-                    sy1 += (sy1 - sy2) * (yaxis.max - y2) / (y2 - y1);
-                    y2 = yaxis.max;
-                }
-                
-                x1 = xaxis.p2c(x1);
-                x2 = xaxis.p2c(x2);
-                y1 = yaxis.p2c(y1);
-                y2 = yaxis.p2c(y2);
-                
-                // the transformation may have swapped us
-                if (x1 > x2) {
-                    tmp = x2;
-                    x2 = x1;
-                    x1 = tmp;
-                }
-                if (y1 > y2) {
-                    tmp = y2;
-                    y2 = y1;
-                    y1 = tmp;
-                }
-
-                tmp = ctx.globalAlpha;
-                ctx.globalAlpha *= series.images.alpha;
-                ctx.drawImage(img,
-                              sx1, sy1, sx2 - sx1, sy2 - sy1,
-                              x1 + plotOffset.left, y1 + plotOffset.top,
-                              x2 - x1, y2 - y1);
-                ctx.globalAlpha = tmp;
-            }
-        });
-    }
-
-    function processRawData(plot, series, data, datapoints) {
-        if (!series.images.show)
-            return;
-
-        // format is Image, x1, y1, x2, y2 (opposite corners)
-        datapoints.format = [
-            { required: true },
-            { x: true, number: true, required: true },
-            { y: true, number: true, required: true },
-            { x: true, number: true, required: true },
-            { y: true, number: true, required: true }
-        ];
-    }
-    
-    function init(plot) {
-        plot.hooks.processRawData.push(processRawData);
-        plot.hooks.draw.push(draw);
-    }
-    
-    $.plot.plugins.push({
-        init: init,
-        options: options,
-        name: 'image',
-        version: '1.1'
-    });
-})(jQuery);
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.image.min.js
+++ /dev/null
@@ -1,1 +0,0 @@
-(function(D){var B={series:{images:{show:false,alpha:1,anchor:"corner"}}};D.plot.image={};D.plot.image.loadDataImages=function(G,F,K){var J=[],H=[];var I=F.series.images.show;D.each(G,function(L,M){if(!(I||M.images.show)){return }if(M.data){M=M.data}D.each(M,function(N,O){if(typeof O[0]=="string"){J.push(O[0]);H.push(O)}})});D.plot.image.load(J,function(L){D.each(H,function(N,O){var M=O[0];if(L[M]){O[0]=L[M]}});K()})};D.plot.image.load=function(H,I){var G=H.length,F={};if(G==0){I({})}D.each(H,function(K,J){var L=function(){--G;F[J]=this;if(G==0){I(F)}};D("<img />").load(L).error(L).attr("src",J)})};function A(H,F){var G=H.getPlotOffset();D.each(H.getData(),function(O,P){var X=P.datapoints.points,I=P.datapoints.pointsize;for(var O=0;O<X.length;O+=I){var Q=X[O],M=X[O+1],V=X[O+2],K=X[O+3],T=X[O+4],W=P.xaxis,S=P.yaxis,N;if(!Q||Q.width<=0||Q.height<=0){continue}if(M>K){N=K;K=M;M=N}if(V>T){N=T;T=V;V=N}if(P.images.anchor=="center"){N=0.5*(K-M)/(Q.width-1);M-=N;K+=N;N=0.5*(T-V)/(Q.height-1);V-=N;T+=N}if(M==K||V==T||M>=W.max||K<=W.min||V>=S.max||T<=S.min){continue}var L=0,U=0,J=Q.width,R=Q.height;if(M<W.min){L+=(J-L)*(W.min-M)/(K-M);M=W.min}if(K>W.max){J+=(J-L)*(W.max-K)/(K-M);K=W.max}if(V<S.min){R+=(U-R)*(S.min-V)/(T-V);V=S.min}if(T>S.max){U+=(U-R)*(S.max-T)/(T-V);T=S.max}M=W.p2c(M);K=W.p2c(K);V=S.p2c(V);T=S.p2c(T);if(M>K){N=K;K=M;M=N}if(V>T){N=T;T=V;V=N}N=F.globalAlpha;F.globalAlpha*=P.images.alpha;F.drawImage(Q,L,U,J-L,R-U,M+G.left,V+G.top,K-M,T-V);F.globalAlpha=N}})}function C(I,F,G,H){if(!F.images.show){return }H.format=[{required:true},{x:true,number:true,required:true},{y:true,number:true,required:true},{x:true,number:true,required:true},{y:true,number:true,required:true}]}function E(F){F.hooks.processRawData.push(C);F.hooks.draw.push(A)}D.plot.plugins.push({init:E,options:B,name:"image",version:"1.1"})})(jQuery);
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.js
+++ /dev/null
@@ -1,2119 +0,0 @@
-/* Javascript plotting library for jQuery, v. 0.6.
- *
- * Released under the MIT license by IOLA, December 2007.
- *
- */
-
-// first an inline dependency, jquery.colorhelpers.js, we inline it here
-// for convenience
-
-/* Plugin for jQuery for working with colors.
- * 
- * Version 1.0.
- * 
- * Inspiration from jQuery color animation plugin by John Resig.
- *
- * Released under the MIT license by Ole Laursen, October 2009.
- *
- * Examples:
- *
- *   $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
- *   var c = $.color.extract($("#mydiv"), 'background-color');
- *   console.log(c.r, c.g, c.b, c.a);
- *   $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
- *
- * Note that .scale() and .add() work in-place instead of returning
- * new objects.
- */ 
-(function(){jQuery.color={};jQuery.color.make=function(E,D,B,C){var F={};F.r=E||0;F.g=D||0;F.b=B||0;F.a=C!=null?C:1;F.add=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]+=H}return F.normalize()};F.scale=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]*=H}return F.normalize()};F.toString=function(){if(F.a>=1){return"rgb("+[F.r,F.g,F.b].join(",")+")"}else{return"rgba("+[F.r,F.g,F.b,F.a].join(",")+")"}};F.normalize=function(){function G(I,J,H){return J<I?I:(J>H?H:J)}F.r=G(0,parseInt(F.r),255);F.g=G(0,parseInt(F.g),255);F.b=G(0,parseInt(F.b),255);F.a=G(0,F.a,1);return F};F.clone=function(){return jQuery.color.make(F.r,F.b,F.g,F.a)};return F.normalize()};jQuery.color.extract=function(C,B){var D;do{D=C.css(B).toLowerCase();if(D!=""&&D!="transparent"){break}C=C.parent()}while(!jQuery.nodeName(C.get(0),"body"));if(D=="rgba(0, 0, 0, 0)"){D="transparent"}return jQuery.color.parse(D)};jQuery.color.parse=function(E){var D,B=jQuery.color.make;if(D=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10))}if(D=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10),parseFloat(D[4]))}if(D=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55)}if(D=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55,parseFloat(D[4]))}if(D=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(E)){return B(parseInt(D[1],16),parseInt(D[2],16),parseInt(D[3],16))}if(D=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(E)){return B(parseInt(D[1]+D[1],16),parseInt(D[2]+D[2],16),parseInt(D[3]+D[3],16))}var C=jQuery.trim(E).toLowerCase();if(C=="transparent"){return B(255,255,255,0)}else{D=A[C];return B(D[0],D[1],D[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();
-
-// the actual Flot code
-(function($) {
-    function Plot(placeholder, data_, options_, plugins) {
-        // data is on the form:
-        //   [ series1, series2 ... ]
-        // where series is either just the data as [ [x1, y1], [x2, y2], ... ]
-        // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... }
-        
-        var series = [],
-            options = {
-                // the color theme used for graphs
-                colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],
-                legend: {
-                    show: true,
-                    noColumns: 1, // number of colums in legend table
-                    labelFormatter: null, // fn: string -> string
-                    labelBoxBorderColor: "#ccc", // border color for the little label boxes
-                    container: null, // container (as jQuery object) to put legend in, null means default on top of graph
-                    position: "ne", // position of default legend container within plot
-                    margin: 5, // distance from grid edge to default legend container within plot
-                    backgroundColor: null, // null means auto-detect
-                    backgroundOpacity: 0.85 // set to 0 to avoid background
-                },
-                xaxis: {
-                    mode: null, // null or "time"
-                    transform: null, // null or f: number -> number to transform axis
-                    inverseTransform: null, // if transform is set, this should be the inverse function
-                    min: null, // min. value to show, null means set automatically
-                    max: null, // max. value to show, null means set automatically
-                    autoscaleMargin: null, // margin in % to add if auto-setting min/max
-                    ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
-                    tickFormatter: null, // fn: number -> string
-                    labelWidth: null, // size of tick labels in pixels
-                    labelHeight: null,
-                    
-                    // mode specific options
-                    tickDecimals: null, // no. of decimals, null means auto
-                    tickSize: null, // number or [number, "unit"]
-                    minTickSize: null, // number or [number, "unit"]
-                    monthNames: null, // list of names of months
-                    timeformat: null, // format string to use
-                    twelveHourClock: false // 12 or 24 time in time mode
-                },
-                yaxis: {
-                    autoscaleMargin: 0.02
-                },
-                x2axis: {
-                    autoscaleMargin: null
-                },
-                y2axis: {
-                    autoscaleMargin: 0.02
-                },
-                series: {
-                    points: {
-                        show: false,
-                        radius: 3,
-                        lineWidth: 2, // in pixels
-                        fill: true,
-                        fillColor: "#ffffff"
-                    },
-                    lines: {
-                        // we don't put in show: false so we can see
-                        // whether lines were actively disabled 
-                        lineWidth: 2, // in pixels
-                        fill: false,
-                        fillColor: null,
-                        steps: false
-                    },
-                    bars: {
-                        show: false,
-                        lineWidth: 2, // in pixels
-                        barWidth: 1, // in units of the x axis
-                        fill: true,
-                        fillColor: null,
-                        align: "left", // or "center" 
-                        horizontal: false // when horizontal, left is now top
-                    },
-                    shadowSize: 3
-                },
-                grid: {
-                    show: true,
-                    aboveData: false,
-                    color: "#545454", // primary color used for outline and labels
-                    backgroundColor: null, // null for transparent, else color
-                    tickColor: "rgba(0,0,0,0.15)", // color used for the ticks
-                    labelMargin: 5, // in pixels
-                    borderWidth: 2, // in pixels
-                    borderColor: null, // set if different from the grid color
-                    markings: null, // array of ranges or fn: axes -> array of ranges
-                    markingsColor: "#f4f4f4",
-                    markingsLineWidth: 2,
-                    // interactive stuff
-                    clickable: false,
-                    hoverable: false,
-                    autoHighlight: true, // highlight in case mouse is near
-                    mouseActiveRadius: 10 // how far the mouse can be away to activate an item
-                },
-                hooks: {}
-            },
-        canvas = null,      // the canvas for the plot itself
-        overlay = null,     // canvas for interactive stuff on top of plot
-        eventHolder = null, // jQuery object that events should be bound to
-        ctx = null, octx = null,
-        axes = { xaxis: {}, yaxis: {}, x2axis: {}, y2axis: {} },
-        plotOffset = { left: 0, right: 0, top: 0, bottom: 0},
-        canvasWidth = 0, canvasHeight = 0,
-        plotWidth = 0, plotHeight = 0,
-        hooks = {
-            processOptions: [],
-            processRawData: [],
-            processDatapoints: [],
-            draw: [],
-            bindEvents: [],
-            drawOverlay: []
-        },
-        plot = this;
-
-        // public functions
-        plot.setData = setData;
-        plot.setupGrid = setupGrid;
-        plot.draw = draw;
-        plot.getPlaceholder = function() { return placeholder; };
-        plot.getCanvas = function() { return canvas; };
-        plot.getPlotOffset = function() { return plotOffset; };
-        plot.width = function () { return plotWidth; };
-        plot.height = function () { return plotHeight; };
-        plot.offset = function () {
-            var o = eventHolder.offset();
-            o.left += plotOffset.left;
-            o.top += plotOffset.top;
-            return o;
-        };
-        plot.getData = function() { return series; };
-        plot.getAxes = function() { return axes; };
-        plot.getOptions = function() { return options; };
-        plot.highlight = highlight;
-        plot.unhighlight = unhighlight;
-        plot.triggerRedrawOverlay = triggerRedrawOverlay;
-        plot.pointOffset = function(point) {
-            return { left: parseInt(axisSpecToRealAxis(point, "xaxis").p2c(+point.x) + plotOffset.left),
-                     top: parseInt(axisSpecToRealAxis(point, "yaxis").p2c(+point.y) + plotOffset.top) };
-        };
-        
-
-        // public attributes
-        plot.hooks = hooks;
-        
-        // initialize
-        initPlugins(plot);
-        parseOptions(options_);
-        constructCanvas();
-        setData(data_);
-        setupGrid();
-        draw();
-        bindEvents();
-
-
-        function executeHooks(hook, args) {
-            args = [plot].concat(args);
-            for (var i = 0; i < hook.length; ++i)
-                hook[i].apply(this, args);
-        }
-
-        function initPlugins() {
-            for (var i = 0; i < plugins.length; ++i) {
-                var p = plugins[i];
-                p.init(plot);
-                if (p.options)
-                    $.extend(true, options, p.options);
-            }
-        }
-        
-        function parseOptions(opts) {
-            $.extend(true, options, opts);
-            if (options.grid.borderColor == null)
-                options.grid.borderColor = options.grid.color;
-            // backwards compatibility, to be removed in future
-            if (options.xaxis.noTicks && options.xaxis.ticks == null)
-                options.xaxis.ticks = options.xaxis.noTicks;
-            if (options.yaxis.noTicks && options.yaxis.ticks == null)
-                options.yaxis.ticks = options.yaxis.noTicks;
-            if (options.grid.coloredAreas)
-                options.grid.markings = options.grid.coloredAreas;
-            if (options.grid.coloredAreasColor)
-                options.grid.markingsColor = options.grid.coloredAreasColor;
-            if (options.lines)
-                $.extend(true, options.series.lines, options.lines);
-            if (options.points)
-                $.extend(true, options.series.points, options.points);
-            if (options.bars)
-                $.extend(true, options.series.bars, options.bars);
-            if (options.shadowSize)
-                options.series.shadowSize = options.shadowSize;
-
-            for (var n in hooks)
-                if (options.hooks[n] && options.hooks[n].length)
-                    hooks[n] = hooks[n].concat(options.hooks[n]);
-
-            executeHooks(hooks.processOptions, [options]);
-        }
-
-        function setData(d) {
-            series = parseData(d);
-            fillInSeriesOptions();
-            processData();
-        }
-        
-        function parseData(d) {
-            var res = [];
-            for (var i = 0; i < d.length; ++i) {
-                var s = $.extend(true, {}, options.series);
-
-                if (d[i].data) {
-                    s.data = d[i].data; // move the data instead of deep-copy
-                    delete d[i].data;
-
-                    $.extend(true, s, d[i]);
-
-                    d[i].data = s.data;
-                }
-                else
-                    s.data = d[i];
-                res.push(s);
-            }
-
-            return res;
-        }
-        
-        function axisSpecToRealAxis(obj, attr) {
-            var a = obj[attr];
-            if (!a || a == 1)
-                return axes[attr];
-            if (typeof a == "number")
-                return axes[attr.charAt(0) + a + attr.slice(1)];
-            return a; // assume it's OK
-        }
-        
-        function fillInSeriesOptions() {
-            var i;
-            
-            // collect what we already got of colors
-            var neededColors = series.length,
-                usedColors = [],
-                assignedColors = [];
-            for (i = 0; i < series.length; ++i) {
-                var sc = series[i].color;
-                if (sc != null) {
-                    --neededColors;
-                    if (typeof sc == "number")
-                        assignedColors.push(sc);
-                    else
-                        usedColors.push($.color.parse(series[i].color));
-                }
-            }
-            
-            // we might need to generate more colors if higher indices
-            // are assigned
-            for (i = 0; i < assignedColors.length; ++i) {
-                neededColors = Math.max(neededColors, assignedColors[i] + 1);
-            }
-
-            // produce colors as needed
-            var colors = [], variation = 0;
-            i = 0;
-            while (colors.length < neededColors) {
-                var c;
-                if (options.colors.length == i) // check degenerate case
-                    c = $.color.make(100, 100, 100);
-                else
-                    c = $.color.parse(options.colors[i]);
-
-                // vary color if needed
-                var sign = variation % 2 == 1 ? -1 : 1;
-                c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2)
-
-                // FIXME: if we're getting to close to something else,
-                // we should probably skip this one
-                colors.push(c);
-                
-                ++i;
-                if (i >= options.colors.length) {
-                    i = 0;
-                    ++variation;
-                }
-            }
-
-            // fill in the options
-            var colori = 0, s;
-            for (i = 0; i < series.length; ++i) {
-                s = series[i];
-                
-                // assign colors
-                if (s.color == null) {
-                    s.color = colors[colori].toString();
-                    ++colori;
-                }
-                else if (typeof s.color == "number")
-                    s.color = colors[s.color].toString();
-
-                // turn on lines automatically in case nothing is set
-                if (s.lines.show == null) {
-                    var v, show = true;
-                    for (v in s)
-                        if (s[v].show) {
-                            show = false;
-                            break;
-                        }
-                    if (show)
-                        s.lines.show = true;
-                }
-
-                // setup axes
-                s.xaxis = axisSpecToRealAxis(s, "xaxis");
-                s.yaxis = axisSpecToRealAxis(s, "yaxis");
-            }
-        }
-        
-        function processData() {
-            var topSentry = Number.POSITIVE_INFINITY,
-                bottomSentry = Number.NEGATIVE_INFINITY,
-                i, j, k, m, length,
-                s, points, ps, x, y, axis, val, f, p;
-
-            for (axis in axes) {
-                axes[axis].datamin = topSentry;
-                axes[axis].datamax = bottomSentry;
-                axes[axis].used = false;
-            }
-
-            function updateAxis(axis, min, max) {
-                if (min < axis.datamin)
-                    axis.datamin = min;
-                if (max > axis.datamax)
-                    axis.datamax = max;
-            }
-
-            for (i = 0; i < series.length; ++i) {
-                s = series[i];
-                s.datapoints = { points: [] };
-                
-                executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]);
-            }
-            
-            // first pass: clean and copy data
-            for (i = 0; i < series.length; ++i) {
-                s = series[i];
-
-                var data = s.data, format = s.datapoints.format;
-
-                if (!format) {
-                    format = [];
-                    // find out how to copy
-                    format.push({ x: true, number: true, required: true });
-                    format.push({ y: true, number: true, required: true });
-
-                    if (s.bars.show)
-                        format.push({ y: true, number: true, required: false, defaultValue: 0 });
-                    
-                    s.datapoints.format = format;
-                }
-
-                if (s.datapoints.pointsize != null)
-                    continue; // already filled in
-
-                if (s.datapoints.pointsize == null)
-                    s.datapoints.pointsize = format.length;
-                
-                ps = s.datapoints.pointsize;
-                points = s.datapoints.points;
-
-                insertSteps = s.lines.show && s.lines.steps;
-                s.xaxis.used = s.yaxis.used = true;
-                
-                for (j = k = 0; j < data.length; ++j, k += ps) {
-                    p = data[j];
-
-                    var nullify = p == null;
-                    if (!nullify) {
-                        for (m = 0; m < ps; ++m) {
-                            val = p[m];
-                            f = format[m];
-
-                            if (f) {
-                                if (f.number && val != null) {
-                                    val = +val; // convert to number
-                                    if (isNaN(val))
-                                        val = null;
-                                }
-
-                                if (val == null) {
-                                    if (f.required)
-                                        nullify = true;
-                                    
-                                    if (f.defaultValue != null)
-                                        val = f.defaultValue;
-                                }
-                            }
-                            
-                            points[k + m] = val;
-                        }
-                    }
-                    
-                    if (nullify) {
-                        for (m = 0; m < ps; ++m) {
-                            val = points[k + m];
-                            if (val != null) {
-                                f = format[m];
-                                // extract min/max info
-                                if (f.x)
-                                    updateAxis(s.xaxis, val, val);
-                                if (f.y)
-                                    updateAxis(s.yaxis, val, val);
-                            }
-                            points[k + m] = null;
-                        }
-                    }
-                    else {
-                        // a little bit of line specific stuff that
-                        // perhaps shouldn't be here, but lacking
-                        // better means...
-                        if (insertSteps && k > 0
-                            && points[k - ps] != null
-                            && points[k - ps] != points[k]
-                            && points[k - ps + 1] != points[k + 1]) {
-                            // copy the point to make room for a middle point
-                            for (m = 0; m < ps; ++m)
-                                points[k + ps + m] = points[k + m];
-
-                            // middle point has same y
-                            points[k + 1] = points[k - ps + 1];
-
-                            // we've added a point, better reflect that
-                            k += ps;
-                        }
-                    }
-                }
-            }
-
-            // give the hooks a chance to run
-            for (i = 0; i < series.length; ++i) {
-                s = series[i];
-                
-                executeHooks(hooks.processDatapoints, [ s, s.datapoints]);
-            }
-
-            // second pass: find datamax/datamin for auto-scaling
-            for (i = 0; i < series.length; ++i) {
-                s = series[i];
-                points = s.datapoints.points,
-                ps = s.datapoints.pointsize;
-
-                var xmin = topSentry, ymin = topSentry,
-                    xmax = bottomSentry, ymax = bottomSentry;
-                
-                for (j = 0; j < points.length; j += ps) {
-                    if (points[j] == null)
-                        continue;
-
-                    for (m = 0; m < ps; ++m) {
-                        val = points[j + m];
-                        f = format[m];
-                        if (!f)
-                            continue;
-                        
-                        if (f.x) {
-                            if (val < xmin)
-                                xmin = val;
-                            if (val > xmax)
-                                xmax = val;
-                        }
-                        if (f.y) {
-                            if (val < ymin)
-                                ymin = val;
-                            if (val > ymax)
-                                ymax = val;
-                        }
-                    }
-                }
-                
-                if (s.bars.show) {
-                    // make sure we got room for the bar on the dancing floor
-                    var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2;
-                    if (s.bars.horizontal) {
-                        ymin += delta;
-                        ymax += delta + s.bars.barWidth;
-                    }
-                    else {
-                        xmin += delta;
-                        xmax += delta + s.bars.barWidth;
-                    }
-                }
-                
-                updateAxis(s.xaxis, xmin, xmax);
-                updateAxis(s.yaxis, ymin, ymax);
-            }
-
-            for (axis in axes) {
-                if (axes[axis].datamin == topSentry)
-                    axes[axis].datamin = null;
-                if (axes[axis].datamax == bottomSentry)
-                    axes[axis].datamax = null;
-            }
-        }
-
-        function constructCanvas() {
-            function makeCanvas(width, height) {
-                var c = document.createElement('canvas');
-                c.width = width;
-                c.height = height;
-                if ($.browser.msie) // excanvas hack
-                    c = window.G_vmlCanvasManager.initElement(c);
-                return c;
-            }
-            
-            canvasWidth = placeholder.width();
-            canvasHeight = placeholder.height();
-            placeholder.html(""); // clear placeholder
-            if (placeholder.css("position") == 'static')
-                placeholder.css("position", "relative"); // for positioning labels and overlay
-
-            if (canvasWidth <= 0 || canvasHeight <= 0)
-                throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight;
-
-            if ($.browser.msie) // excanvas hack
-                window.G_vmlCanvasManager.init_(document); // make sure everything is setup
-            
-            // the canvas
-            canvas = $(makeCanvas(canvasWidth, canvasHeight)).appendTo(placeholder).get(0);
-            ctx = canvas.getContext("2d");
-
-            // overlay canvas for interactive features
-            overlay = $(makeCanvas(canvasWidth, canvasHeight)).css({ position: 'absolute', left: 0, top: 0 }).appendTo(placeholder).get(0);
-            octx = overlay.getContext("2d");
-            octx.stroke();
-        }
-
-        function bindEvents() {
-            // we include the canvas in the event holder too, because IE 7
-            // sometimes has trouble with the stacking order
-            eventHolder = $([overlay, canvas]);
-
-            // bind events
-            if (options.grid.hoverable)
-                eventHolder.mousemove(onMouseMove);
-
-            if (options.grid.clickable)
-                eventHolder.click(onClick);
-
-            executeHooks(hooks.bindEvents, [eventHolder]);
-        }
-
-        function setupGrid() {
-            function setTransformationHelpers(axis, o) {
-                function identity(x) { return x; }
-                
-                var s, m, t = o.transform || identity,
-                    it = o.inverseTransform;
-                    
-                // add transformation helpers
-                if (axis == axes.xaxis || axis == axes.x2axis) {
-                    // precompute how much the axis is scaling a point
-                    // in canvas space
-                    s = axis.scale = plotWidth / (t(axis.max) - t(axis.min));
-                    m = t(axis.min);
-
-                    // data point to canvas coordinate
-                    if (t == identity) // slight optimization
-                        axis.p2c = function (p) { return (p - m) * s; };
-                    else
-                        axis.p2c = function (p) { return (t(p) - m) * s; };
-                    // canvas coordinate to data point
-                    if (!it)
-                        axis.c2p = function (c) { return m + c / s; };
-                    else
-                        axis.c2p = function (c) { return it(m + c / s); };
-                }
-                else {
-                    s = axis.scale = plotHeight / (t(axis.max) - t(axis.min));
-                    m = t(axis.max);
-                    
-                    if (t == identity)
-                        axis.p2c = function (p) { return (m - p) * s; };
-                    else
-                        axis.p2c = function (p) { return (m - t(p)) * s; };
-                    if (!it)
-                        axis.c2p = function (c) { return m - c / s; };
-                    else
-                        axis.c2p = function (c) { return it(m - c / s); };
-                }
-            }
-
-            function measureLabels(axis, axisOptions) {
-                var i, labels = [], l;
-                
-                axis.labelWidth = axisOptions.labelWidth;
-                axis.labelHeight = axisOptions.labelHeight;
-
-                if (axis == axes.xaxis || axis == axes.x2axis) {
-                    // to avoid measuring the widths of the labels, we
-                    // construct fixed-size boxes and put the labels inside
-                    // them, we don't need the exact figures and the
-                    // fixed-size box content is easy to center
-                    if (axis.labelWidth == null)
-                        axis.labelWidth = canvasWidth / (axis.ticks.length > 0 ? axis.ticks.length : 1);
-
-                    // measure x label heights
-                    if (axis.labelHeight == null) {
-                        labels = [];
-                        for (i = 0; i < axis.ticks.length; ++i) {
-                            l = axis.ticks[i].label;
-                            if (l)
-                                labels.push('<div class="tickLabel" style="float:left;width:' + axis.labelWidth + 'px">' + l + '</div>');
-                        }
-                        
-                        if (labels.length > 0) {
-                            var dummyDiv = $('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">'
-                                             + labels.join("") + '<div style="clear:left"></div></div>').appendTo(placeholder);
-                            axis.labelHeight = dummyDiv.height();
-                            dummyDiv.remove();
-                        }
-                    }
-                }
-                else if (axis.labelWidth == null || axis.labelHeight == null) {
-                    // calculate y label dimensions
-                    for (i = 0; i < axis.ticks.length; ++i) {
-                        l = axis.ticks[i].label;
-                        if (l)
-                            labels.push('<div class="tickLabel">' + l + '</div>');
-                    }
-                    
-                    if (labels.length > 0) {
-                        var dummyDiv = $('<div style="position:absolute;top:-10000px;font-size:smaller">'
-                                         + labels.join("") + '</div>').appendTo(placeholder);
-                        if (axis.labelWidth == null)
-                            axis.labelWidth = dummyDiv.width();
-                        if (axis.labelHeight == null)
-                            axis.labelHeight = dummyDiv.find("div").height();
-                        dummyDiv.remove();
-                    }
-                    
-                }
-
-                if (axis.labelWidth == null)
-                    axis.labelWidth = 0;
-                if (axis.labelHeight == null)
-                    axis.labelHeight = 0;
-            }
-            
-            function setGridSpacing() {
-                // get the most space needed around the grid for things
-                // that may stick out
-                var maxOutset = options.grid.borderWidth;
-                for (i = 0; i < series.length; ++i)
-                    maxOutset = Math.max(maxOutset, 2 * (series[i].points.radius + series[i].points.lineWidth/2));
-                
-                plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = maxOutset;
-                
-                var margin = options.grid.labelMargin + options.grid.borderWidth;
-                
-                if (axes.xaxis.labelHeight > 0)
-                    plotOffset.bottom = Math.max(maxOutset, axes.xaxis.labelHeight + margin);
-                if (axes.yaxis.labelWidth > 0)
-                    plotOffset.left = Math.max(maxOutset, axes.yaxis.labelWidth + margin);
-                if (axes.x2axis.labelHeight > 0)
-                    plotOffset.top = Math.max(maxOutset, axes.x2axis.labelHeight + margin);
-                if (axes.y2axis.labelWidth > 0)
-                    plotOffset.right = Math.max(maxOutset, axes.y2axis.labelWidth + margin);
-            
-                plotWidth = canvasWidth - plotOffset.left - plotOffset.right;
-                plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top;
-            }
-            
-            var axis;
-            for (axis in axes)
-                setRange(axes[axis], options[axis]);
-            
-            if (options.grid.show) {
-                for (axis in axes) {
-                    prepareTickGeneration(axes[axis], options[axis]);
-                    setTicks(axes[axis], options[axis]);
-                    measureLabels(axes[axis], options[axis]);
-                }
-
-                setGridSpacing();
-            }
-            else {
-                plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0;
-                plotWidth = canvasWidth;
-                plotHeight = canvasHeight;
-            }
-            
-            for (axis in axes)
-                setTransformationHelpers(axes[axis], options[axis]);
-
-            if (options.grid.show)
-                insertLabels();
-            
-            insertLegend();
-        }
-        
-        function setRange(axis, axisOptions) {
-            var min = +(axisOptions.min != null ? axisOptions.min : axis.datamin),
-                max = +(axisOptions.max != null ? axisOptions.max : axis.datamax),
-                delta = max - min;
-
-            if (delta == 0.0) {
-                // degenerate case
-                var widen = max == 0 ? 1 : 0.01;
-
-                if (axisOptions.min == null)
-                    min -= widen;
-                // alway widen max if we couldn't widen min to ensure we
-                // don't fall into min == max which doesn't work
-                if (axisOptions.max == null || axisOptions.min != null)
-                    max += widen;
-            }
-            else {
-                // consider autoscaling
-                var margin = axisOptions.autoscaleMargin;
-                if (margin != null) {
-                    if (axisOptions.min == null) {
-                        min -= delta * margin;
-                        // make sure we don't go below zero if all values
-                        // are positive
-                        if (min < 0 && axis.datamin != null && axis.datamin >= 0)
-                            min = 0;
-                    }
-                    if (axisOptions.max == null) {
-                        max += delta * margin;
-                        if (max > 0 && axis.datamax != null && axis.datamax <= 0)
-                            max = 0;
-                    }
-                }
-            }
-            axis.min = min;
-            axis.max = max;
-        }
-
-        function prepareTickGeneration(axis, axisOptions) {
-            // estimate number of ticks
-            var noTicks;
-            if (typeof axisOptions.ticks == "number" && axisOptions.ticks > 0)
-                noTicks = axisOptions.ticks;
-            else if (axis == axes.xaxis || axis == axes.x2axis)
-                 // heuristic based on the model a*sqrt(x) fitted to
-                 // some reasonable data points
-                noTicks = 0.3 * Math.sqrt(canvasWidth);
-            else
-                noTicks = 0.3 * Math.sqrt(canvasHeight);
-            
-            var delta = (axis.max - axis.min) / noTicks,
-                size, generator, unit, formatter, i, magn, norm;
-
-            if (axisOptions.mode == "time") {
-                // pretty handling of time
-                
-                // map of app. size of time units in milliseconds
-                var timeUnitSize = {
-                    "second": 1000,
-                    "minute": 60 * 1000,
-                    "hour": 60 * 60 * 1000,
-                    "day": 24 * 60 * 60 * 1000,
-                    "month": 30 * 24 * 60 * 60 * 1000,
-                    "year": 365.2425 * 24 * 60 * 60 * 1000
-                };
-
-
-                // the allowed tick sizes, after 1 year we use
-                // an integer algorithm
-                var spec = [
-                    [1, "second"], [2, "second"], [5, "second"], [10, "second"],
-                    [30, "second"], 
-                    [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
-                    [30, "minute"], 
-                    [1, "hour"], [2, "hour"], [4, "hour"],
-                    [8, "hour"], [12, "hour"],
-                    [1, "day"], [2, "day"], [3, "day"],
-                    [0.25, "month"], [0.5, "month"], [1, "month"],
-                    [2, "month"], [3, "month"], [6, "month"],
-                    [1, "year"]
-                ];
-
-                var minSize = 0;
-                if (axisOptions.minTickSize != null) {
-                    if (typeof axisOptions.tickSize == "number")
-                        minSize = axisOptions.tickSize;
-                    else
-                        minSize = axisOptions.minTickSize[0] * timeUnitSize[axisOptions.minTickSize[1]];
-                }
-
-                for (i = 0; i < spec.length - 1; ++i)
-                    if (delta < (spec[i][0] * timeUnitSize[spec[i][1]]
-                                 + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
-                       && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize)
-                        break;
-                size = spec[i][0];
-                unit = spec[i][1];
-                
-                // special-case the possibility of several years
-                if (unit == "year") {
-                    magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10));
-                    norm = (delta / timeUnitSize.year) / magn;
-                    if (norm < 1.5)
-                        size = 1;
-                    else if (norm < 3)
-                        size = 2;
-                    else if (norm < 7.5)
-                        size = 5;
-                    else
-                        size = 10;
-
-                    size *= magn;
-                }
-
-                if (axisOptions.tickSize) {
-                    size = axisOptions.tickSize[0];
-                    unit = axisOptions.tickSize[1];
-                }
-                
-                generator = function(axis) {
-                    var ticks = [],
-                        tickSize = axis.tickSize[0], unit = axis.tickSize[1],
-                        d = new Date(axis.min);
-                    
-                    var step = tickSize * timeUnitSize[unit];
-
-                    if (unit == "second")
-                        d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize));
-                    if (unit == "minute")
-                        d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize));
-                    if (unit == "hour")
-                        d.setUTCHours(floorInBase(d.getUTCHours(), tickSize));
-                    if (unit == "month")
-                        d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize));
-                    if (unit == "year")
-                        d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize));
-                    
-                    // reset smaller components
-                    d.setUTCMilliseconds(0);
-                    if (step >= timeUnitSize.minute)
-                        d.setUTCSeconds(0);
-                    if (step >= timeUnitSize.hour)
-                        d.setUTCMinutes(0);
-                    if (step >= timeUnitSize.day)
-                        d.setUTCHours(0);
-                    if (step >= timeUnitSize.day * 4)
-                        d.setUTCDate(1);
-                    if (step >= timeUnitSize.year)
-                        d.setUTCMonth(0);
-
-
-                    var carry = 0, v = Number.NaN, prev;
-                    do {
-                        prev = v;
-                        v = d.getTime();
-                        ticks.push({ v: v, label: axis.tickFormatter(v, axis) });
-                        if (unit == "month") {
-                            if (tickSize < 1) {
-                                // a bit complicated - we'll divide the month
-                                // up but we need to take care of fractions
-                                // so we don't end up in the middle of a day
-                                d.setUTCDate(1);
-                                var start = d.getTime();
-                                d.setUTCMonth(d.getUTCMonth() + 1);
-                                var end = d.getTime();
-                                d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
-                                carry = d.getUTCHours();
-                                d.setUTCHours(0);
-                            }
-                            else
-                                d.setUTCMonth(d.getUTCMonth() + tickSize);
-                        }
-                        else if (unit == "year") {
-                            d.setUTCFullYear(d.getUTCFullYear() + tickSize);
-                        }
-                        else
-                            d.setTime(v + step);
-                    } while (v < axis.max && v != prev);
-
-                    return ticks;
-                };
-
-                formatter = function (v, axis) {
-                    var d = new Date(v);
-
-                    // first check global format
-                    if (axisOptions.timeformat != null)
-                        return $.plot.formatDate(d, axisOptions.timeformat, axisOptions.monthNames);
-                    
-                    var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
-                    var span = axis.max - axis.min;
-                    var suffix = (axisOptions.twelveHourClock) ? " %p" : "";
-                    
-                    if (t < timeUnitSize.minute)
-                        fmt = "%h:%M:%S" + suffix;
-                    else if (t < timeUnitSize.day) {
-                        if (span < 2 * timeUnitSize.day)
-                            fmt = "%h:%M" + suffix;
-                        else
-                            fmt = "%b %d %h:%M" + suffix;
-                    }
-                    else if (t < timeUnitSize.month)
-                        fmt = "%b %d";
-                    else if (t < timeUnitSize.year) {
-                        if (span < timeUnitSize.year)
-                            fmt = "%b";
-                        else
-                            fmt = "%b %y";
-                    }
-                    else
-                        fmt = "%y";
-                    
-                    return $.plot.formatDate(d, fmt, axisOptions.monthNames);
-                };
-            }
-            else {
-                // pretty rounding of base-10 numbers
-                var maxDec = axisOptions.tickDecimals;
-                var dec = -Math.floor(Math.log(delta) / Math.LN10);
-                if (maxDec != null && dec > maxDec)
-                    dec = maxDec;
-
-                magn = Math.pow(10, -dec);
-                norm = delta / magn; // norm is between 1.0 and 10.0
-                
-                if (norm < 1.5)
-                    size = 1;
-                else if (norm < 3) {
-                    size = 2;
-                    // special case for 2.5, requires an extra decimal
-                    if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
-                        size = 2.5;
-                        ++dec;
-                    }
-                }
-                else if (norm < 7.5)
-                    size = 5;
-                else
-                    size = 10;
-
-                size *= magn;
-                
-                if (axisOptions.minTickSize != null && size < axisOptions.minTickSize)
-                    size = axisOptions.minTickSize;
-
-                if (axisOptions.tickSize != null)
-                    size = axisOptions.tickSize;
-
-                axis.tickDecimals = Math.max(0, (maxDec != null) ? maxDec : dec);
-
-                generator = function (axis) {
-                    var ticks = [];
-
-                    // spew out all possible ticks
-                    var start = floorInBase(axis.min, axis.tickSize),
-                        i = 0, v = Number.NaN, prev;
-                    do {
-                        prev = v;
-                        v = start + i * axis.tickSize;
-                        ticks.push({ v: v, label: axis.tickFormatter(v, axis) });
-                        ++i;
-                    } while (v < axis.max && v != prev);
-                    return ticks;
-                };
-
-                formatter = function (v, axis) {
-                    return v.toFixed(axis.tickDecimals);
-                };
-            }
-
-            axis.tickSize = unit ? [size, unit] : size;
-            axis.tickGenerator = generator;
-            if ($.isFunction(axisOptions.tickFormatter))
-                axis.tickFormatter = function (v, axis) { return "" + axisOptions.tickFormatter(v, axis); };
-            else
-                axis.tickFormatter = formatter;
-        }
-        
-        function setTicks(axis, axisOptions) {
-            axis.ticks = [];
-
-            if (!axis.used)
-                return;
-            
-            if (axisOptions.ticks == null)
-                axis.ticks = axis.tickGenerator(axis);
-            else if (typeof axisOptions.ticks == "number") {
-                if (axisOptions.ticks > 0)
-                    axis.ticks = axis.tickGenerator(axis);
-            }
-            else if (axisOptions.ticks) {
-                var ticks = axisOptions.ticks;
-
-                if ($.isFunction(ticks))
-                    // generate the ticks
-                    ticks = ticks({ min: axis.min, max: axis.max });
-                
-                // clean up the user-supplied ticks, copy them over
-                var i, v;
-                for (i = 0; i < ticks.length; ++i) {
-                    var label = null;
-                    var t = ticks[i];
-                    if (typeof t == "object") {
-                        v = t[0];
-                        if (t.length > 1)
-                            label = t[1];
-                    }
-                    else
-                        v = t;
-                    if (label == null)
-                        label = axis.tickFormatter(v, axis);
-                    axis.ticks[i] = { v: v, label: label };
-                }
-            }
-
-            if (axisOptions.autoscaleMargin != null && axis.ticks.length > 0) {
-                // snap to ticks
-                if (axisOptions.min == null)
-                    axis.min = Math.min(axis.min, axis.ticks[0].v);
-                if (axisOptions.max == null && axis.ticks.length > 1)
-                    axis.max = Math.max(axis.max, axis.ticks[axis.ticks.length - 1].v);
-            }
-        }
-      
-        function draw() {
-            ctx.clearRect(0, 0, canvasWidth, canvasHeight);
-
-            var grid = options.grid;
-            
-            if (grid.show && !grid.aboveData)
-                drawGrid();
-
-            for (var i = 0; i < series.length; ++i)
-                drawSeries(series[i]);
-
-            executeHooks(hooks.draw, [ctx]);
-            
-            if (grid.show && grid.aboveData)
-                drawGrid();
-        }
-
-        function extractRange(ranges, coord) {
-            var firstAxis = coord + "axis",
-                secondaryAxis = coord + "2axis",
-                axis, from, to, reverse;
-
-            if (ranges[firstAxis]) {
-                axis = axes[firstAxis];
-                from = ranges[firstAxis].from;
-                to = ranges[firstAxis].to;
-            }
-            else if (ranges[secondaryAxis]) {
-                axis = axes[secondaryAxis];
-                from = ranges[secondaryAxis].from;
-                to = ranges[secondaryAxis].to;
-            }
-            else {
-                // backwards-compat stuff - to be removed in future
-                axis = axes[firstAxis];
-                from = ranges[coord + "1"];
-                to = ranges[coord + "2"];
-            }
-
-            // auto-reverse as an added bonus
-            if (from != null && to != null && from > to)
-                return { from: to, to: from, axis: axis };
-            
-            return { from: from, to: to, axis: axis };
-        }
-        
-        function drawGrid() {
-            var i;
-            
-            ctx.save();
-            ctx.translate(plotOffset.left, plotOffset.top);
-
-            // draw background, if any
-            if (options.grid.backgroundColor) {
-                ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");
-                ctx.fillRect(0, 0, plotWidth, plotHeight);
-            }
-
-            // draw markings
-            var markings = options.grid.markings;
-            if (markings) {
-                if ($.isFunction(markings))
-                    // xmin etc. are backwards-compatible, to be removed in future
-                    markings = markings({ xmin: axes.xaxis.min, xmax: axes.xaxis.max, ymin: axes.yaxis.min, ymax: axes.yaxis.max, xaxis: axes.xaxis, yaxis: axes.yaxis, x2axis: axes.x2axis, y2axis: axes.y2axis });
-
-                for (i = 0; i < markings.length; ++i) {
-                    var m = markings[i],
-                        xrange = extractRange(m, "x"),
-                        yrange = extractRange(m, "y");
-
-                    // fill in missing
-                    if (xrange.from == null)
-                        xrange.from = xrange.axis.min;
-                    if (xrange.to == null)
-                        xrange.to = xrange.axis.max;
-                    if (yrange.from == null)
-                        yrange.from = yrange.axis.min;
-                    if (yrange.to == null)
-                        yrange.to = yrange.axis.max;
-
-                    // clip
-                    if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||
-                        yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)
-                        continue;
-
-                    xrange.from = Math.max(xrange.from, xrange.axis.min);
-                    xrange.to = Math.min(xrange.to, xrange.axis.max);
-                    yrange.from = Math.max(yrange.from, yrange.axis.min);
-                    yrange.to = Math.min(yrange.to, yrange.axis.max);
-
-                    if (xrange.from == xrange.to && yrange.from == yrange.to)
-                        continue;
-
-                    // then draw
-                    xrange.from = xrange.axis.p2c(xrange.from);
-                    xrange.to = xrange.axis.p2c(xrange.to);
-                    yrange.from = yrange.axis.p2c(yrange.from);
-                    yrange.to = yrange.axis.p2c(yrange.to);
-                    
-                    if (xrange.from == xrange.to || yrange.from == yrange.to) {
-                        // draw line
-                        ctx.beginPath();
-                        ctx.strokeStyle = m.color || options.grid.markingsColor;
-                        ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;
-                        //ctx.moveTo(Math.floor(xrange.from), yrange.from);
-                        //ctx.lineTo(Math.floor(xrange.to), yrange.to);
-                        ctx.moveTo(xrange.from, yrange.from);
-                        ctx.lineTo(xrange.to, yrange.to);
-                        ctx.stroke();
-                    }
-                    else {
-                        // fill area
-                        ctx.fillStyle = m.color || options.grid.markingsColor;
-                        ctx.fillRect(xrange.from, yrange.to,
-                                     xrange.to - xrange.from,
-                                     yrange.from - yrange.to);
-                    }
-                }
-            }
-            
-            // draw the inner grid
-            ctx.lineWidth = 1;
-            ctx.strokeStyle = options.grid.tickColor;
-            ctx.beginPath();
-            var v, axis = axes.xaxis;
-            for (i = 0; i < axis.ticks.length; ++i) {
-                v = axis.ticks[i].v;
-                if (v <= axis.min || v >= axes.xaxis.max)
-                    continue;   // skip those lying on the axes
-
-                ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 0);
-                ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, plotHeight);
-            }
-
-            axis = axes.yaxis;
-            for (i = 0; i < axis.ticks.length; ++i) {
-                v = axis.ticks[i].v;
-                if (v <= axis.min || v >= axis.max)
-                    continue;
-
-                ctx.moveTo(0, Math.floor(axis.p2c(v)) + ctx.lineWidth/2);
-                ctx.lineTo(plotWidth, Math.floor(axis.p2c(v)) + ctx.lineWidth/2);
-            }
-
-            axis = axes.x2axis;
-            for (i = 0; i < axis.ticks.length; ++i) {
-                v = axis.ticks[i].v;
-                if (v <= axis.min || v >= axis.max)
-                    continue;
-    
-                ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, -5);
-                ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 5);
-            }
-
-            axis = axes.y2axis;
-            for (i = 0; i < axis.ticks.length; ++i) {
-                v = axis.ticks[i].v;
-                if (v <= axis.min || v >= axis.max)
-                    continue;
-
-                ctx.moveTo(plotWidth-5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2);
-                ctx.lineTo(plotWidth+5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2);
-            }
-            
-            ctx.stroke();
-            
-            if (options.grid.borderWidth) {
-                // draw border
-                var bw = options.grid.borderWidth;
-                ctx.lineWidth = bw;
-                ctx.strokeStyle = options.grid.borderColor;
-                ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
-            }
-
-            ctx.restore();
-        }
-
-        function insertLabels() {
-            placeholder.find(".tickLabels").remove();
-            
-            var html = ['<div class="tickLabels" style="font-size:smaller;color:' + options.grid.color + '">'];
-
-            function addLabels(axis, labelGenerator) {
-                for (var i = 0; i < axis.ticks.length; ++i) {
-                    var tick = axis.ticks[i];
-                    if (!tick.label || tick.v < axis.min || tick.v > axis.max)
-                        continue;
-                    html.push(labelGenerator(tick, axis));
-                }
-            }
-
-            var margin = options.grid.labelMargin + options.grid.borderWidth;
-            
-            addLabels(axes.xaxis, function (tick, axis) {
-                return '<div style="position:absolute;top:' + (plotOffset.top + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>";
-            });
-            
-            
-            addLabels(axes.yaxis, function (tick, axis) {
-                return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;right:' + (plotOffset.right + plotWidth + margin) + 'px;width:' + axis.labelWidth + 'px;text-align:right" class="tickLabel">' + tick.label + "</div>";
-            });
-            
-            addLabels(axes.x2axis, function (tick, axis) {
-                return '<div style="position:absolute;bottom:' + (plotOffset.bottom + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>";
-            });
-            
-            addLabels(axes.y2axis, function (tick, axis) {
-                return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;left:' + (plotOffset.left + plotWidth + margin) +'px;width:' + axis.labelWidth + 'px;text-align:left" class="tickLabel">' + tick.label + "</div>";
-            });
-
-            html.push('</div>');
-            
-            placeholder.append(html.join(""));
-        }
-
-        function drawSeries(series) {
-            if (series.lines.show)
-                drawSeriesLines(series);
-            if (series.bars.show)
-                drawSeriesBars(series);
-            if (series.points.show)
-                drawSeriesPoints(series);
-        }
-        
-        function drawSeriesLines(series) {
-            function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
-                var points = datapoints.points,
-                    ps = datapoints.pointsize,
-                    prevx = null, prevy = null;
-                
-                ctx.beginPath();
-                for (var i = ps; i < points.length; i += ps) {
-                    var x1 = points[i - ps], y1 = points[i - ps + 1],
-                        x2 = points[i], y2 = points[i + 1];
-                    
-                    if (x1 == null || x2 == null)
-                        continue;
-
-                    // clip with ymin
-                    if (y1 <= y2 && y1 < axisy.min) {
-                        if (y2 < axisy.min)
-                            continue;   // line segment is outside
-                        // compute new intersection point
-                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
-                        y1 = axisy.min;
-                    }
-                    else if (y2 <= y1 && y2 < axisy.min) {
-                        if (y1 < axisy.min)
-                            continue;
-                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
-                        y2 = axisy.min;
-                    }
-
-                    // clip with ymax
-                    if (y1 >= y2 && y1 > axisy.max) {
-                        if (y2 > axisy.max)
-                            continue;
-                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
-                        y1 = axisy.max;
-                    }
-                    else if (y2 >= y1 && y2 > axisy.max) {
-                        if (y1 > axisy.max)
-                            continue;
-                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
-                        y2 = axisy.max;
-                    }
-
-                    // clip with xmin
-                    if (x1 <= x2 && x1 < axisx.min) {
-                        if (x2 < axisx.min)
-                            continue;
-                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
-                        x1 = axisx.min;
-                    }
-                    else if (x2 <= x1 && x2 < axisx.min) {
-                        if (x1 < axisx.min)
-                            continue;
-                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
-                        x2 = axisx.min;
-                    }
-
-                    // clip with xmax
-                    if (x1 >= x2 && x1 > axisx.max) {
-                        if (x2 > axisx.max)
-                            continue;
-                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
-                        x1 = axisx.max;
-                    }
-                    else if (x2 >= x1 && x2 > axisx.max) {
-                        if (x1 > axisx.max)
-                            continue;
-                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
-                        x2 = axisx.max;
-                    }
-
-                    if (x1 != prevx || y1 != prevy)
-                        ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
-                    
-                    prevx = x2;
-                    prevy = y2;
-                    ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
-                }
-                ctx.stroke();
-            }
-
-            function plotLineArea(datapoints, axisx, axisy) {
-                var points = datapoints.points,
-                    ps = datapoints.pointsize,
-                    bottom = Math.min(Math.max(0, axisy.min), axisy.max),
-                    top, lastX = 0, areaOpen = false;
-                
-                for (var i = ps; i < points.length; i += ps) {
-                    var x1 = points[i - ps], y1 = points[i - ps + 1],
-                        x2 = points[i], y2 = points[i + 1];
-                    
-                    if (areaOpen && x1 != null && x2 == null) {
-                        // close area
-                        ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom));
-                        ctx.fill();
-                        areaOpen = false;
-                        continue;
-                    }
-
-                    if (x1 == null || x2 == null)
-                        continue;
-
-                    // clip x values
-                    
-                    // clip with xmin
-                    if (x1 <= x2 && x1 < axisx.min) {
-                        if (x2 < axisx.min)
-                            continue;
-                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
-                        x1 = axisx.min;
-                    }
-                    else if (x2 <= x1 && x2 < axisx.min) {
-                        if (x1 < axisx.min)
-                            continue;
-                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
-                        x2 = axisx.min;
-                    }
-
-                    // clip with xmax
-                    if (x1 >= x2 && x1 > axisx.max) {
-                        if (x2 > axisx.max)
-                            continue;
-                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
-                        x1 = axisx.max;
-                    }
-                    else if (x2 >= x1 && x2 > axisx.max) {
-                        if (x1 > axisx.max)
-                            continue;
-                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
-                        x2 = axisx.max;
-                    }
-
-                    if (!areaOpen) {
-                        // open area
-                        ctx.beginPath();
-                        ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
-                        areaOpen = true;
-                    }
-                    
-                    // now first check the case where both is outside
-                    if (y1 >= axisy.max && y2 >= axisy.max) {
-                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
-                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
-                        lastX = x2;
-                        continue;
-                    }
-                    else if (y1 <= axisy.min && y2 <= axisy.min) {
-                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
-                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
-                        lastX = x2;
-                        continue;
-                    }
-                    
-                    // else it's a bit more complicated, there might
-                    // be two rectangles and two triangles we need to fill
-                    // in; to find these keep track of the current x values
-                    var x1old = x1, x2old = x2;
-
-                    // and clip the y values, without shortcutting
-                    
-                    // clip with ymin
-                    if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
-                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
-                        y1 = axisy.min;
-                    }
-                    else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
-                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
-                        y2 = axisy.min;
-                    }
-
-                    // clip with ymax
-                    if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
-                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
-                        y1 = axisy.max;
-                    }
-                    else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
-                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
-                        y2 = axisy.max;
-                    }
-
-
-                    // if the x value was changed we got a rectangle
-                    // to fill
-                    if (x1 != x1old) {
-                        if (y1 <= axisy.min)
-                            top = axisy.min;
-                        else
-                            top = axisy.max;
-                        
-                        ctx.lineTo(axisx.p2c(x1old), axisy.p2c(top));
-                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(top));
-                    }
-                    
-                    // fill the triangles
-                    ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
-                    ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
-
-                    // fill the other rectangle if it's there
-                    if (x2 != x2old) {
-                        if (y2 <= axisy.min)
-                            top = axisy.min;
-                        else
-                            top = axisy.max;
-                        
-                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(top));
-                        ctx.lineTo(axisx.p2c(x2old), axisy.p2c(top));
-                    }
-
-                    lastX = Math.max(x2, x2old);
-                }
-
-                if (areaOpen) {
-                    ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom));
-                    ctx.fill();
-                }
-            }
-            
-            ctx.save();
-            ctx.translate(plotOffset.left, plotOffset.top);
-            ctx.lineJoin = "round";
-
-            var lw = series.lines.lineWidth,
-                sw = series.shadowSize;
-            // FIXME: consider another form of shadow when filling is turned on
-            if (lw > 0 && sw > 0) {
-                // draw shadow as a thick and thin line with transparency
-                ctx.lineWidth = sw;
-                ctx.strokeStyle = "rgba(0,0,0,0.1)";
-                // position shadow at angle from the mid of line
-                var angle = Math.PI/18;
-                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis);
-                ctx.lineWidth = sw/2;
-                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis);
-            }
-
-            ctx.lineWidth = lw;
-            ctx.strokeStyle = series.color;
-            var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);
-            if (fillStyle) {
-                ctx.fillStyle = fillStyle;
-                plotLineArea(series.datapoints, series.xaxis, series.yaxis);
-            }
-
-            if (lw > 0)
-                plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);
-            ctx.restore();
-        }
-
-        function drawSeriesPoints(series) {
-            function plotPoints(datapoints, radius, fillStyle, offset, circumference, axisx, axisy) {
-                var points = datapoints.points, ps = datapoints.pointsize;
-                
-                for (var i = 0; i < points.length; i += ps) {
-                    var x = points[i], y = points[i + 1];
-                    if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
-                        continue;
-                    
-                    ctx.beginPath();
-                    ctx.arc(axisx.p2c(x), axisy.p2c(y) + offset, radius, 0, circumference, false);
-                    if (fillStyle) {
-                        ctx.fillStyle = fillStyle;
-                        ctx.fill();
-                    }
-                    ctx.stroke();
-                }
-            }
-            
-            ctx.save();
-            ctx.translate(plotOffset.left, plotOffset.top);
-
-            var lw = series.lines.lineWidth,
-                sw = series.shadowSize,
-                radius = series.points.radius;
-            if (lw > 0 && sw > 0) {
-                // draw shadow in two steps
-                var w = sw / 2;
-                ctx.lineWidth = w;
-                ctx.strokeStyle = "rgba(0,0,0,0.1)";
-                plotPoints(series.datapoints, radius, null, w + w/2, Math.PI,
-                           series.xaxis, series.yaxis);
-
-                ctx.strokeStyle = "rgba(0,0,0,0.2)";
-                plotPoints(series.datapoints, radius, null, w/2, Math.PI,
-                           series.xaxis, series.yaxis);
-            }
-
-            ctx.lineWidth = lw;
-            ctx.strokeStyle = series.color;
-            plotPoints(series.datapoints, radius,
-                       getFillStyle(series.points, series.color), 0, 2 * Math.PI,
-                       series.xaxis, series.yaxis);
-            ctx.restore();
-        }
-
-        function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal) {
-            var left, right, bottom, top,
-                drawLeft, drawRight, drawTop, drawBottom,
-                tmp;
-
-            if (horizontal) {
-                drawBottom = drawRight = drawTop = true;
-                drawLeft = false;
-                left = b;
-                right = x;
-                top = y + barLeft;
-                bottom = y + barRight;
-
-                // account for negative bars
-                if (right < left) {
-                    tmp = right;
-                    right = left;
-                    left = tmp;
-                    drawLeft = true;
-                    drawRight = false;
-                }
-            }
-            else {
-                drawLeft = drawRight = drawTop = true;
-                drawBottom = false;
-                left = x + barLeft;
-                right = x + barRight;
-                bottom = b;
-                top = y;
-
-                // account for negative bars
-                if (top < bottom) {
-                    tmp = top;
-                    top = bottom;
-                    bottom = tmp;
-                    drawBottom = true;
-                    drawTop = false;
-                }
-            }
-           
-            // clip
-            if (right < axisx.min || left > axisx.max ||
-                top < axisy.min || bottom > axisy.max)
-                return;
-            
-            if (left < axisx.min) {
-                left = axisx.min;
-                drawLeft = false;
-            }
-
-            if (right > axisx.max) {
-                right = axisx.max;
-                drawRight = false;
-            }
-
-            if (bottom < axisy.min) {
-                bottom = axisy.min;
-                drawBottom = false;
-            }
-            
-            if (top > axisy.max) {
-                top = axisy.max;
-                drawTop = false;
-            }
-
-            left = axisx.p2c(left);
-            bottom = axisy.p2c(bottom);
-            right = axisx.p2c(right);
-            top = axisy.p2c(top);
-            
-            // fill the bar
-            if (fillStyleCallback) {
-                c.beginPath();
-                c.moveTo(left, bottom);
-                c.lineTo(left, top);
-                c.lineTo(right, top);
-                c.lineTo(right, bottom);
-                c.fillStyle = fillStyleCallback(bottom, top);
-                c.fill();
-            }
-
-            // draw outline
-            if (drawLeft || drawRight || drawTop || drawBottom) {
-                c.beginPath();
-
-                // FIXME: inline moveTo is buggy with excanvas
-                c.moveTo(left, bottom + offset);
-                if (drawLeft)
-                    c.lineTo(left, top + offset);
-                else
-                    c.moveTo(left, top + offset);
-                if (drawTop)
-                    c.lineTo(right, top + offset);
-                else
-                    c.moveTo(right, top + offset);
-                if (drawRight)
-                    c.lineTo(right, bottom + offset);
-                else
-                    c.moveTo(right, bottom + offset);
-                if (drawBottom)
-                    c.lineTo(left, bottom + offset);
-                else
-                    c.moveTo(left, bottom + offset);
-                c.stroke();
-            }
-        }
-        
-        function drawSeriesBars(series) {
-            function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) {
-                var points = datapoints.points, ps = datapoints.pointsize;
-                
-                for (var i = 0; i < points.length; i += ps) {
-                    if (points[i] == null)
-                        continue;
-                    drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal);
-                }
-            }
-
-            ctx.save();
-            ctx.translate(plotOffset.left, plotOffset.top);
-
-            // FIXME: figure out a way to add shadows (for instance along the right edge)
-            ctx.lineWidth = series.bars.lineWidth;
-            ctx.strokeStyle = series.color;
-            var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
-            var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
-            plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis);
-            ctx.restore();
-        }
-
-        function getFillStyle(filloptions, seriesColor, bottom, top) {
-            var fill = filloptions.fill;
-            if (!fill)
-                return null;
-
-            if (filloptions.fillColor)
-                return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
-            
-            var c = $.color.parse(seriesColor);
-            c.a = typeof fill == "number" ? fill : 0.4;
-            c.normalize();
-            return c.toString();
-        }
-        
-        function insertLegend() {
-            placeholder.find(".legend").remove();
-
-            if (!options.legend.show)
-                return;
-            
-            var fragments = [], rowStarted = false,
-                lf = options.legend.labelFormatter, s, label;
-            for (i = 0; i < series.length; ++i) {
-                s = series[i];
-                label = s.label;
-                if (!label)
-                    continue;
-                
-                if (i % options.legend.noColumns == 0) {
-                    if (rowStarted)
-                        fragments.push('</tr>');
-                    fragments.push('<tr>');
-                    rowStarted = true;
-                }
-
-                if (lf)
-                    label = lf(label, s);
-                
-                fragments.push(
-                    '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + s.color + ';overflow:hidden"></div></div></td>' +
-                    '<td class="legendLabel">' + label + '</td>');
-            }
-            if (rowStarted)
-                fragments.push('</tr>');
-            
-            if (fragments.length == 0)
-                return;
-
-            var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>';
-            if (options.legend.container != null)
-                $(options.legend.container).html(table);
-            else {
-                var pos = "",
-                    p = options.legend.position,
-                    m = options.legend.margin;
-                if (m[0] == null)
-                    m = [m, m];
-                if (p.charAt(0) == "n")
-                    pos += 'top:' + (m[1] + plotOffset.top) + 'px;';
-                else if (p.charAt(0) == "s")
-                    pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;';
-                if (p.charAt(1) == "e")
-                    pos += 'right:' + (m[0] + plotOffset.right) + 'px;';
-                else if (p.charAt(1) == "w")
-                    pos += 'left:' + (m[0] + plotOffset.left) + 'px;';
-                var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder);
-                if (options.legend.backgroundOpacity != 0.0) {
-                    // put in the transparent background
-                    // separately to avoid blended labels and
-                    // label boxes
-                    var c = options.legend.backgroundColor;
-                    if (c == null) {
-                        c = options.grid.backgroundColor;
-                        if (c && typeof c == "string")
-                            c = $.color.parse(c);
-                        else
-                            c = $.color.extract(legend, 'background-color');
-                        c.a = 1;
-                        c = c.toString();
-                    }
-                    var div = legend.children();
-                    $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
-                }
-            }
-        }
-
-
-        // interactive features
-        
-        var highlights = [],
-            redrawTimeout = null;
-        
-        // returns the data item the mouse is over, or null if none is found
-        function findNearbyItem(mouseX, mouseY, seriesFilter) {
-            var maxDistance = options.grid.mouseActiveRadius,
-                smallestDistance = maxDistance * maxDistance + 1,
-                item = null, foundPoint = false, i, j;
-
-            for (i = 0; i < series.length; ++i) {
-                if (!seriesFilter(series[i]))
-                    continue;
-                
-                var s = series[i],
-                    axisx = s.xaxis,
-                    axisy = s.yaxis,
-                    points = s.datapoints.points,
-                    ps = s.datapoints.pointsize,
-                    mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
-                    my = axisy.c2p(mouseY),
-                    maxx = maxDistance / axisx.scale,
-                    maxy = maxDistance / axisy.scale;
-
-                if (s.lines.show || s.points.show) {
-                    for (j = 0; j < points.length; j += ps) {
-                        var x = points[j], y = points[j + 1];
-                        if (x == null)
-                            continue;
-                        
-                        // For points and lines, the cursor must be within a
-                        // certain distance to the data point
-                        if (x - mx > maxx || x - mx < -maxx ||
-                            y - my > maxy || y - my < -maxy)
-                            continue;
-
-                        // We have to calculate distances in pixels, not in
-                        // data units, because the scales of the axes may be different
-                        var dx = Math.abs(axisx.p2c(x) - mouseX),
-                            dy = Math.abs(axisy.p2c(y) - mouseY),
-                            dist = dx * dx + dy * dy; // we save the sqrt
-
-                        // use <= to ensure last point takes precedence
-                        // (last generally means on top of)
-                        if (dist <= smallestDistance) {
-                            smallestDistance = dist;
-                            item = [i, j / ps];
-                        }
-                    }
-                }
-                    
-                if (s.bars.show && !item) { // no other point can be nearby
-                    var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2,
-                        barRight = barLeft + s.bars.barWidth;
-                    
-                    for (j = 0; j < points.length; j += ps) {
-                        var x = points[j], y = points[j + 1], b = points[j + 2];
-                        if (x == null)
-                            continue;
-  
-                        // for a bar graph, the cursor must be inside the bar
-                        if (series[i].bars.horizontal ? 
-                            (mx <= Math.max(b, x) && mx >= Math.min(b, x) && 
-                             my >= y + barLeft && my <= y + barRight) :
-                            (mx >= x + barLeft && mx <= x + barRight &&
-                             my >= Math.min(b, y) && my <= Math.max(b, y)))
-                                item = [i, j / ps];
-                    }
-                }
-            }
-
-            if (item) {
-                i = item[0];
-                j = item[1];
-                ps = series[i].datapoints.pointsize;
-                
-                return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
-                         dataIndex: j,
-                         series: series[i],
-                         seriesIndex: i };
-            }
-            
-            return null;
-        }
-
-        function onMouseMove(e) {
-            if (options.grid.hoverable)
-                triggerClickHoverEvent("plothover", e,
-                                       function (s) { return s["hoverable"] != false; });
-        }
-        
-        function onClick(e) {
-            triggerClickHoverEvent("plotclick", e,
-                                   function (s) { return s["clickable"] != false; });
-        }
-
-        // trigger click or hover event (they send the same parameters
-        // so we share their code)
-        function triggerClickHoverEvent(eventname, event, seriesFilter) {
-            var offset = eventHolder.offset(),
-                pos = { pageX: event.pageX, pageY: event.pageY },
-                canvasX = event.pageX - offset.left - plotOffset.left,
-                canvasY = event.pageY - offset.top - plotOffset.top;
-
-            if (axes.xaxis.used)
-                pos.x = axes.xaxis.c2p(canvasX);
-            if (axes.yaxis.used)
-                pos.y = axes.yaxis.c2p(canvasY);
-            if (axes.x2axis.used)
-                pos.x2 = axes.x2axis.c2p(canvasX);
-            if (axes.y2axis.used)
-                pos.y2 = axes.y2axis.c2p(canvasY);
-
-            var item = findNearbyItem(canvasX, canvasY, seriesFilter);
-
-            if (item) {
-                // fill in mouse pos for any listeners out there
-                item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left);
-                item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top);
-            }
-
-            if (options.grid.autoHighlight) {
-                // clear auto-highlights
-                for (var i = 0; i < highlights.length; ++i) {
-                    var h = highlights[i];
-                    if (h.auto == eventname &&
-                        !(item && h.series == item.series && h.point == item.datapoint))
-                        unhighlight(h.series, h.point);
-                }
-                
-                if (item)
-                    highlight(item.series, item.datapoint, eventname);
-            }
-            
-            placeholder.trigger(eventname, [ pos, item ]);
-        }
-
-        function triggerRedrawOverlay() {
-            if (!redrawTimeout)
-                redrawTimeout = setTimeout(drawOverlay, 30);
-        }
-
-        function drawOverlay() {
-            redrawTimeout = null;
-
-            // draw highlights
-            octx.save();
-            octx.clearRect(0, 0, canvasWidth, canvasHeight);
-            octx.translate(plotOffset.left, plotOffset.top);
-            
-            var i, hi;
-            for (i = 0; i < highlights.length; ++i) {
-                hi = highlights[i];
-
-                if (hi.series.bars.show)
-                    drawBarHighlight(hi.series, hi.point);
-                else
-                    drawPointHighlight(hi.series, hi.point);
-            }
-            octx.restore();
-            
-            executeHooks(hooks.drawOverlay, [octx]);
-        }
-        
-        function highlight(s, point, auto) {
-            if (typeof s == "number")
-                s = series[s];
-
-            if (typeof point == "number")
-                point = s.data[point];
-
-            var i = indexOfHighlight(s, point);
-            if (i == -1) {
-                highlights.push({ series: s, point: point, auto: auto });
-
-                triggerRedrawOverlay();
-            }
-            else if (!auto)
-                highlights[i].auto = false;
-        }
-            
-        function unhighlight(s, point) {
-            if (s == null && point == null) {
-                highlights = [];
-                triggerRedrawOverlay();
-            }
-            
-            if (typeof s == "number")
-                s = series[s];
-
-            if (typeof point == "number")
-                point = s.data[point];
-
-            var i = indexOfHighlight(s, point);
-            if (i != -1) {
-                highlights.splice(i, 1);
-
-                triggerRedrawOverlay();
-            }
-        }
-        
-        function indexOfHighlight(s, p) {
-            for (var i = 0; i < highlights.length; ++i) {
-                var h = highlights[i];
-                if (h.series == s && h.point[0] == p[0]
-                    && h.point[1] == p[1])
-                    return i;
-            }
-            return -1;
-        }
-        
-        function drawPointHighlight(series, point) {
-            var x = point[0], y = point[1],
-                axisx = series.xaxis, axisy = series.yaxis;
-            
-            if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
-                return;
-            
-            var pointRadius = series.points.radius + series.points.lineWidth / 2;
-            octx.lineWidth = pointRadius;
-            octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
-            var radius = 1.5 * pointRadius;
-            octx.beginPath();
-            octx.arc(axisx.p2c(x), axisy.p2c(y), radius, 0, 2 * Math.PI, false);
-            octx.stroke();
-        }
-
-        function drawBarHighlight(series, point) {
-            octx.lineWidth = series.bars.lineWidth;
-            octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
-            var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString();
-            var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
-            drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
-                    0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal);
-        }
-
-        function getColorOrGradient(spec, bottom, top, defaultColor) {
-            if (typeof spec == "string")
-                return spec;
-            else {
-                // assume this is a gradient spec; IE currently only
-                // supports a simple vertical gradient properly, so that's
-                // what we support too
-                var gradient = ctx.createLinearGradient(0, top, 0, bottom);
-                
-                for (var i = 0, l = spec.colors.length; i < l; ++i) {
-                    var c = spec.colors[i];
-                    if (typeof c != "string") {
-                        c = $.color.parse(defaultColor).scale('rgb', c.brightness);
-                        c.a *= c.opacity;
-                        c = c.toString();
-                    }
-                    gradient.addColorStop(i / (l - 1), c);
-                }
-                
-                return gradient;
-            }
-        }
-    }
-
-    $.plot = function(placeholder, data, options) {
-        var plot = new Plot($(placeholder), data, options, $.plot.plugins);
-        /*var t0 = new Date();
-        var t1 = new Date();
-        var tstr = "time used (msecs): " + (t1.getTime() - t0.getTime())
-        if (window.console)
-            console.log(tstr);
-        else
-            alert(tstr);*/
-        return plot;
-    };
-
-    $.plot.plugins = [];
-
-    // returns a string with the date d formatted according to fmt
-    $.plot.formatDate = function(d, fmt, monthNames) {
-        var leftPad = function(n) {
-            n = "" + n;
-            return n.length == 1 ? "0" + n : n;
-        };
-        
-        var r = [];
-        var escape = false;
-        var hours = d.getUTCHours();
-        var isAM = hours < 12;
-        if (monthNames == null)
-            monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
-
-        if (fmt.search(/%p|%P/) != -1) {
-            if (hours > 12) {
-                hours = hours - 12;
-            } else if (hours == 0) {
-                hours = 12;
-            }
-        }
-        for (var i = 0; i < fmt.length; ++i) {
-            var c = fmt.charAt(i);
-            
-            if (escape) {
-                switch (c) {
-                case 'h': c = "" + hours; break;
-                case 'H': c = leftPad(hours); break;
-                case 'M': c = leftPad(d.getUTCMinutes()); break;
-                case 'S': c = leftPad(d.getUTCSeconds()); break;
-                case 'd': c = "" + d.getUTCDate(); break;
-                case 'm': c = "" + (d.getUTCMonth() + 1); break;
-                case 'y': c = "" + d.getUTCFullYear(); break;
-                case 'b': c = "" + monthNames[d.getUTCMonth()]; break;
-                case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
-                case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
-                }
-                r.push(c);
-                escape = false;
-            }
-            else {
-                if (c == "%")
-                    escape = true;
-                else
-                    r.push(c);
-            }
-        }
-        return r.join("");
-    };
-    
-    // round to nearby lower multiple of base
-    function floorInBase(n, base) {
-        return base * Math.floor(n / base);
-    }
-    
-})(jQuery);
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.min.js
+++ /dev/null
@@ -1,1 +0,0 @@
-(function(){jQuery.color={};jQuery.color.make=function(G,H,J,I){var A={};A.r=G||0;A.g=H||0;A.b=J||0;A.a=I!=null?I:1;A.add=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]+=D}return A.normalize()};A.scale=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]*=D}return A.normalize()};A.toString=function(){if(A.a>=1){return"rgb("+[A.r,A.g,A.b].join(",")+")"}else{return"rgba("+[A.r,A.g,A.b,A.a].join(",")+")"}};A.normalize=function(){function C(E,D,F){return D<E?E:(D>F?F:D)}A.r=C(0,parseInt(A.r),255);A.g=C(0,parseInt(A.g),255);A.b=C(0,parseInt(A.b),255);A.a=C(0,A.a,1);return A};A.clone=function(){return jQuery.color.make(A.r,A.b,A.g,A.a)};return A.normalize()};jQuery.color.extract=function(E,F){var A;do{A=E.css(F).toLowerCase();if(A!=""&&A!="transparent"){break}E=E.parent()}while(!jQuery.nodeName(E.get(0),"body"));if(A=="rgba(0, 0, 0, 0)"){A="transparent"}return jQuery.color.parse(A)};jQuery.color.parse=function(A){var F,H=jQuery.color.make;if(F=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10))}if(F=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10),parseFloat(F[4]))}if(F=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55)}if(F=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55,parseFloat(F[4]))}if(F=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(A)){return H(parseInt(F[1],16),parseInt(F[2],16),parseInt(F[3],16))}if(F=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(A)){return H(parseInt(F[1]+F[1],16),parseInt(F[2]+F[2],16),parseInt(F[3]+F[3],16))}var G=jQuery.trim(A).toLowerCase();if(G=="transparent"){return H(255,255,255,0)}else{F=B[G];return H(F[0],F[1],F[2])}};var B={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();(function(C){function B(l,W,X,E){var O=[],g={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:0.85},xaxis:{mode:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,tickDecimals:null,tickSize:null,minTickSize:null,monthNames:null,timeformat:null,twelveHourClock:false},yaxis:{autoscaleMargin:0.02},x2axis:{autoscaleMargin:null},y2axis:{autoscaleMargin:0.02},series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false},shadowSize:3},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,tickColor:"rgba(0,0,0,0.15)",labelMargin:5,borderWidth:2,borderColor:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},hooks:{}},P=null,AC=null,AD=null,Y=null,AJ=null,s={xaxis:{},yaxis:{},x2axis:{},y2axis:{}},e={left:0,right:0,top:0,bottom:0},y=0,Q=0,I=0,t=0,L={processOptions:[],processRawData:[],processDatapoints:[],draw:[],bindEvents:[],drawOverlay:[]},G=this;G.setData=f;G.setupGrid=k;G.draw=AH;G.getPlaceholder=function(){return l};G.getCanvas=function(){return P};G.getPlotOffset=function(){return e};G.width=function(){return I};G.height=function(){return t};G.offset=function(){var AK=AD.offset();AK.left+=e.left;AK.top+=e.top;return AK};G.getData=function(){return O};G.getAxes=function(){return s};G.getOptions=function(){return g};G.highlight=AE;G.unhighlight=x;G.triggerRedrawOverlay=q;G.pointOffset=function(AK){return{left:parseInt(T(AK,"xaxis").p2c(+AK.x)+e.left),top:parseInt(T(AK,"yaxis").p2c(+AK.y)+e.top)}};G.hooks=L;b(G);r(X);c();f(W);k();AH();AG();function Z(AM,AK){AK=[G].concat(AK);for(var AL=0;AL<AM.length;++AL){AM[AL].apply(this,AK)}}function b(){for(var AK=0;AK<E.length;++AK){var AL=E[AK];AL.init(G);if(AL.options){C.extend(true,g,AL.options)}}}function r(AK){C.extend(true,g,AK);if(g.grid.borderColor==null){g.grid.borderColor=g.grid.color}if(g.xaxis.noTicks&&g.xaxis.ticks==null){g.xaxis.ticks=g.xaxis.noTicks}if(g.yaxis.noTicks&&g.yaxis.ticks==null){g.yaxis.ticks=g.yaxis.noTicks}if(g.grid.coloredAreas){g.grid.markings=g.grid.coloredAreas}if(g.grid.coloredAreasColor){g.grid.markingsColor=g.grid.coloredAreasColor}if(g.lines){C.extend(true,g.series.lines,g.lines)}if(g.points){C.extend(true,g.series.points,g.points)}if(g.bars){C.extend(true,g.series.bars,g.bars)}if(g.shadowSize){g.series.shadowSize=g.shadowSize}for(var AL in L){if(g.hooks[AL]&&g.hooks[AL].length){L[AL]=L[AL].concat(g.hooks[AL])}}Z(L.processOptions,[g])}function f(AK){O=M(AK);U();m()}function M(AN){var AL=[];for(var AK=0;AK<AN.length;++AK){var AM=C.extend(true,{},g.series);if(AN[AK].data){AM.data=AN[AK].data;delete AN[AK].data;C.extend(true,AM,AN[AK]);AN[AK].data=AM.data}else{AM.data=AN[AK]}AL.push(AM)}return AL}function T(AM,AK){var AL=AM[AK];if(!AL||AL==1){return s[AK]}if(typeof AL=="number"){return s[AK.charAt(0)+AL+AK.slice(1)]}return AL}function U(){var AP;var AV=O.length,AK=[],AN=[];for(AP=0;AP<O.length;++AP){var AS=O[AP].color;if(AS!=null){--AV;if(typeof AS=="number"){AN.push(AS)}else{AK.push(C.color.parse(O[AP].color))}}}for(AP=0;AP<AN.length;++AP){AV=Math.max(AV,AN[AP]+1)}var AL=[],AO=0;AP=0;while(AL.length<AV){var AR;if(g.colors.length==AP){AR=C.color.make(100,100,100)}else{AR=C.color.parse(g.colors[AP])}var AM=AO%2==1?-1:1;AR.scale("rgb",1+AM*Math.ceil(AO/2)*0.2);AL.push(AR);++AP;if(AP>=g.colors.length){AP=0;++AO}}var AQ=0,AW;for(AP=0;AP<O.length;++AP){AW=O[AP];if(AW.color==null){AW.color=AL[AQ].toString();++AQ}else{if(typeof AW.color=="number"){AW.color=AL[AW.color].toString()}}if(AW.lines.show==null){var AU,AT=true;for(AU in AW){if(AW[AU].show){AT=false;break}}if(AT){AW.lines.show=true}}AW.xaxis=T(AW,"xaxis");AW.yaxis=T(AW,"yaxis")}}function m(){var AW=Number.POSITIVE_INFINITY,AQ=Number.NEGATIVE_INFINITY,Ac,Aa,AZ,AV,AL,AR,Ab,AX,AP,AO,AK,Ai,Af,AT;for(AK in s){s[AK].datamin=AW;s[AK].datamax=AQ;s[AK].used=false}function AN(Al,Ak,Aj){if(Ak<Al.datamin){Al.datamin=Ak}if(Aj>Al.datamax){Al.datamax=Aj}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];AR.datapoints={points:[]};Z(L.processRawData,[AR,AR.data,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];var Ah=AR.data,Ae=AR.datapoints.format;if(!Ae){Ae=[];Ae.push({x:true,number:true,required:true});Ae.push({y:true,number:true,required:true});if(AR.bars.show){Ae.push({y:true,number:true,required:false,defaultValue:0})}AR.datapoints.format=Ae}if(AR.datapoints.pointsize!=null){continue}if(AR.datapoints.pointsize==null){AR.datapoints.pointsize=Ae.length}AX=AR.datapoints.pointsize;Ab=AR.datapoints.points;insertSteps=AR.lines.show&&AR.lines.steps;AR.xaxis.used=AR.yaxis.used=true;for(Aa=AZ=0;Aa<Ah.length;++Aa,AZ+=AX){AT=Ah[Aa];var AM=AT==null;if(!AM){for(AV=0;AV<AX;++AV){Ai=AT[AV];Af=Ae[AV];if(Af){if(Af.number&&Ai!=null){Ai=+Ai;if(isNaN(Ai)){Ai=null}}if(Ai==null){if(Af.required){AM=true}if(Af.defaultValue!=null){Ai=Af.defaultValue}}}Ab[AZ+AV]=Ai}}if(AM){for(AV=0;AV<AX;++AV){Ai=Ab[AZ+AV];if(Ai!=null){Af=Ae[AV];if(Af.x){AN(AR.xaxis,Ai,Ai)}if(Af.y){AN(AR.yaxis,Ai,Ai)}}Ab[AZ+AV]=null}}else{if(insertSteps&&AZ>0&&Ab[AZ-AX]!=null&&Ab[AZ-AX]!=Ab[AZ]&&Ab[AZ-AX+1]!=Ab[AZ+1]){for(AV=0;AV<AX;++AV){Ab[AZ+AX+AV]=Ab[AZ+AV]}Ab[AZ+1]=Ab[AZ-AX+1];AZ+=AX}}}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Z(L.processDatapoints,[AR,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Ab=AR.datapoints.points,AX=AR.datapoints.pointsize;var AS=AW,AY=AW,AU=AQ,Ad=AQ;for(Aa=0;Aa<Ab.length;Aa+=AX){if(Ab[Aa]==null){continue}for(AV=0;AV<AX;++AV){Ai=Ab[Aa+AV];Af=Ae[AV];if(!Af){continue}if(Af.x){if(Ai<AS){AS=Ai}if(Ai>AU){AU=Ai}}if(Af.y){if(Ai<AY){AY=Ai}if(Ai>Ad){Ad=Ai}}}}if(AR.bars.show){var Ag=AR.bars.align=="left"?0:-AR.bars.barWidth/2;if(AR.bars.horizontal){AY+=Ag;Ad+=Ag+AR.bars.barWidth}else{AS+=Ag;AU+=Ag+AR.bars.barWidth}}AN(AR.xaxis,AS,AU);AN(AR.yaxis,AY,Ad)}for(AK in s){if(s[AK].datamin==AW){s[AK].datamin=null}if(s[AK].datamax==AQ){s[AK].datamax=null}}}function c(){function AK(AM,AL){var AN=document.createElement("canvas");AN.width=AM;AN.height=AL;if(C.browser.msie){AN=window.G_vmlCanvasManager.initElement(AN)}return AN}y=l.width();Q=l.height();l.html("");if(l.css("position")=="static"){l.css("position","relative")}if(y<=0||Q<=0){throw"Invalid dimensions for plot, width = "+y+", height = "+Q}if(C.browser.msie){window.G_vmlCanvasManager.init_(document)}P=C(AK(y,Q)).appendTo(l).get(0);Y=P.getContext("2d");AC=C(AK(y,Q)).css({position:"absolute",left:0,top:0}).appendTo(l).get(0);AJ=AC.getContext("2d");AJ.stroke()}function AG(){AD=C([AC,P]);if(g.grid.hoverable){AD.mousemove(D)}if(g.grid.clickable){AD.click(d)}Z(L.bindEvents,[AD])}function k(){function AL(AT,AU){function AP(AV){return AV}var AS,AO,AQ=AU.transform||AP,AR=AU.inverseTransform;if(AT==s.xaxis||AT==s.x2axis){AS=AT.scale=I/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.min);if(AQ==AP){AT.p2c=function(AV){return(AV-AO)*AS}}else{AT.p2c=function(AV){return(AQ(AV)-AO)*AS}}if(!AR){AT.c2p=function(AV){return AO+AV/AS}}else{AT.c2p=function(AV){return AR(AO+AV/AS)}}}else{AS=AT.scale=t/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.max);if(AQ==AP){AT.p2c=function(AV){return(AO-AV)*AS}}else{AT.p2c=function(AV){return(AO-AQ(AV))*AS}}if(!AR){AT.c2p=function(AV){return AO-AV/AS}}else{AT.c2p=function(AV){return AR(AO-AV/AS)}}}}function AN(AR,AT){var AQ,AS=[],AP;AR.labelWidth=AT.labelWidth;AR.labelHeight=AT.labelHeight;if(AR==s.xaxis||AR==s.x2axis){if(AR.labelWidth==null){AR.labelWidth=y/(AR.ticks.length>0?AR.ticks.length:1)}if(AR.labelHeight==null){AS=[];for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel" style="float:left;width:'+AR.labelWidth+'px">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">'+AS.join("")+'<div style="clear:left"></div></div>').appendTo(l);AR.labelHeight=AO.height();AO.remove()}}}else{if(AR.labelWidth==null||AR.labelHeight==null){for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;font-size:smaller">'+AS.join("")+"</div>").appendTo(l);if(AR.labelWidth==null){AR.labelWidth=AO.width()}if(AR.labelHeight==null){AR.labelHeight=AO.find("div").height()}AO.remove()}}}if(AR.labelWidth==null){AR.labelWidth=0}if(AR.labelHeight==null){AR.labelHeight=0}}function AM(){var AP=g.grid.borderWidth;for(i=0;i<O.length;++i){AP=Math.max(AP,2*(O[i].points.radius+O[i].points.lineWidth/2))}e.left=e.right=e.top=e.bottom=AP;var AO=g.grid.labelMargin+g.grid.borderWidth;if(s.xaxis.labelHeight>0){e.bottom=Math.max(AP,s.xaxis.labelHeight+AO)}if(s.yaxis.labelWidth>0){e.left=Math.max(AP,s.yaxis.labelWidth+AO)}if(s.x2axis.labelHeight>0){e.top=Math.max(AP,s.x2axis.labelHeight+AO)}if(s.y2axis.labelWidth>0){e.right=Math.max(AP,s.y2axis.labelWidth+AO)}I=y-e.left-e.right;t=Q-e.bottom-e.top}var AK;for(AK in s){K(s[AK],g[AK])}if(g.grid.show){for(AK in s){F(s[AK],g[AK]);p(s[AK],g[AK]);AN(s[AK],g[AK])}AM()}else{e.left=e.right=e.top=e.bottom=0;I=y;t=Q}for(AK in s){AL(s[AK],g[AK])}if(g.grid.show){h()}AI()}function K(AN,AQ){var AM=+(AQ.min!=null?AQ.min:AN.datamin),AK=+(AQ.max!=null?AQ.max:AN.datamax),AP=AK-AM;if(AP==0){var AL=AK==0?1:0.01;if(AQ.min==null){AM-=AL}if(AQ.max==null||AQ.min!=null){AK+=AL}}else{var AO=AQ.autoscaleMargin;if(AO!=null){if(AQ.min==null){AM-=AP*AO;if(AM<0&&AN.datamin!=null&&AN.datamin>=0){AM=0}}if(AQ.max==null){AK+=AP*AO;if(AK>0&&AN.datamax!=null&&AN.datamax<=0){AK=0}}}}AN.min=AM;AN.max=AK}function F(AP,AS){var AO;if(typeof AS.ticks=="number"&&AS.ticks>0){AO=AS.ticks}else{if(AP==s.xaxis||AP==s.x2axis){AO=0.3*Math.sqrt(y)}else{AO=0.3*Math.sqrt(Q)}}var AX=(AP.max-AP.min)/AO,AZ,AT,AV,AW,AR,AM,AL;if(AS.mode=="time"){var AU={second:1000,minute:60*1000,hour:60*60*1000,day:24*60*60*1000,month:30*24*60*60*1000,year:365.2425*24*60*60*1000};var AY=[[1,"second"],[2,"second"],[5,"second"],[10,"second"],[30,"second"],[1,"minute"],[2,"minute"],[5,"minute"],[10,"minute"],[30,"minute"],[1,"hour"],[2,"hour"],[4,"hour"],[8,"hour"],[12,"hour"],[1,"day"],[2,"day"],[3,"day"],[0.25,"month"],[0.5,"month"],[1,"month"],[2,"month"],[3,"month"],[6,"month"],[1,"year"]];var AN=0;if(AS.minTickSize!=null){if(typeof AS.tickSize=="number"){AN=AS.tickSize}else{AN=AS.minTickSize[0]*AU[AS.minTickSize[1]]}}for(AR=0;AR<AY.length-1;++AR){if(AX<(AY[AR][0]*AU[AY[AR][1]]+AY[AR+1][0]*AU[AY[AR+1][1]])/2&&AY[AR][0]*AU[AY[AR][1]]>=AN){break}}AZ=AY[AR][0];AV=AY[AR][1];if(AV=="year"){AM=Math.pow(10,Math.floor(Math.log(AX/AU.year)/Math.LN10));AL=(AX/AU.year)/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM}if(AS.tickSize){AZ=AS.tickSize[0];AV=AS.tickSize[1]}AT=function(Ac){var Ah=[],Af=Ac.tickSize[0],Ai=Ac.tickSize[1],Ag=new Date(Ac.min);var Ab=Af*AU[Ai];if(Ai=="second"){Ag.setUTCSeconds(A(Ag.getUTCSeconds(),Af))}if(Ai=="minute"){Ag.setUTCMinutes(A(Ag.getUTCMinutes(),Af))}if(Ai=="hour"){Ag.setUTCHours(A(Ag.getUTCHours(),Af))}if(Ai=="month"){Ag.setUTCMonth(A(Ag.getUTCMonth(),Af))}if(Ai=="year"){Ag.setUTCFullYear(A(Ag.getUTCFullYear(),Af))}Ag.setUTCMilliseconds(0);if(Ab>=AU.minute){Ag.setUTCSeconds(0)}if(Ab>=AU.hour){Ag.setUTCMinutes(0)}if(Ab>=AU.day){Ag.setUTCHours(0)}if(Ab>=AU.day*4){Ag.setUTCDate(1)}if(Ab>=AU.year){Ag.setUTCMonth(0)}var Ak=0,Aj=Number.NaN,Ad;do{Ad=Aj;Aj=Ag.getTime();Ah.push({v:Aj,label:Ac.tickFormatter(Aj,Ac)});if(Ai=="month"){if(Af<1){Ag.setUTCDate(1);var Aa=Ag.getTime();Ag.setUTCMonth(Ag.getUTCMonth()+1);var Ae=Ag.getTime();Ag.setTime(Aj+Ak*AU.hour+(Ae-Aa)*Af);Ak=Ag.getUTCHours();Ag.setUTCHours(0)}else{Ag.setUTCMonth(Ag.getUTCMonth()+Af)}}else{if(Ai=="year"){Ag.setUTCFullYear(Ag.getUTCFullYear()+Af)}else{Ag.setTime(Aj+Ab)}}}while(Aj<Ac.max&&Aj!=Ad);return Ah};AW=function(Aa,Ad){var Af=new Date(Aa);if(AS.timeformat!=null){return C.plot.formatDate(Af,AS.timeformat,AS.monthNames)}var Ab=Ad.tickSize[0]*AU[Ad.tickSize[1]];var Ac=Ad.max-Ad.min;var Ae=(AS.twelveHourClock)?" %p":"";if(Ab<AU.minute){fmt="%h:%M:%S"+Ae}else{if(Ab<AU.day){if(Ac<2*AU.day){fmt="%h:%M"+Ae}else{fmt="%b %d %h:%M"+Ae}}else{if(Ab<AU.month){fmt="%b %d"}else{if(Ab<AU.year){if(Ac<AU.year){fmt="%b"}else{fmt="%b %y"}}else{fmt="%y"}}}}return C.plot.formatDate(Af,fmt,AS.monthNames)}}else{var AK=AS.tickDecimals;var AQ=-Math.floor(Math.log(AX)/Math.LN10);if(AK!=null&&AQ>AK){AQ=AK}AM=Math.pow(10,-AQ);AL=AX/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2;if(AL>2.25&&(AK==null||AQ+1<=AK)){AZ=2.5;++AQ}}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM;if(AS.minTickSize!=null&&AZ<AS.minTickSize){AZ=AS.minTickSize}if(AS.tickSize!=null){AZ=AS.tickSize}AP.tickDecimals=Math.max(0,(AK!=null)?AK:AQ);AT=function(Ac){var Ae=[];var Af=A(Ac.min,Ac.tickSize),Ab=0,Aa=Number.NaN,Ad;do{Ad=Aa;Aa=Af+Ab*Ac.tickSize;Ae.push({v:Aa,label:Ac.tickFormatter(Aa,Ac)});++Ab}while(Aa<Ac.max&&Aa!=Ad);return Ae};AW=function(Aa,Ab){return Aa.toFixed(Ab.tickDecimals)}}AP.tickSize=AV?[AZ,AV]:AZ;AP.tickGenerator=AT;if(C.isFunction(AS.tickFormatter)){AP.tickFormatter=function(Aa,Ab){return""+AS.tickFormatter(Aa,Ab)}}else{AP.tickFormatter=AW}}function p(AO,AQ){AO.ticks=[];if(!AO.used){return }if(AQ.ticks==null){AO.ticks=AO.tickGenerator(AO)}else{if(typeof AQ.ticks=="number"){if(AQ.ticks>0){AO.ticks=AO.tickGenerator(AO)}}else{if(AQ.ticks){var AP=AQ.ticks;if(C.isFunction(AP)){AP=AP({min:AO.min,max:AO.max})}var AN,AK;for(AN=0;AN<AP.length;++AN){var AL=null;var AM=AP[AN];if(typeof AM=="object"){AK=AM[0];if(AM.length>1){AL=AM[1]}}else{AK=AM}if(AL==null){AL=AO.tickFormatter(AK,AO)}AO.ticks[AN]={v:AK,label:AL}}}}}if(AQ.autoscaleMargin!=null&&AO.ticks.length>0){if(AQ.min==null){AO.min=Math.min(AO.min,AO.ticks[0].v)}if(AQ.max==null&&AO.ticks.length>1){AO.max=Math.max(AO.max,AO.ticks[AO.ticks.length-1].v)}}}function AH(){Y.clearRect(0,0,y,Q);var AL=g.grid;if(AL.show&&!AL.aboveData){S()}for(var AK=0;AK<O.length;++AK){AA(O[AK])}Z(L.draw,[Y]);if(AL.show&&AL.aboveData){S()}}function N(AL,AR){var AO=AR+"axis",AK=AR+"2axis",AN,AQ,AP,AM;if(AL[AO]){AN=s[AO];AQ=AL[AO].from;AP=AL[AO].to}else{if(AL[AK]){AN=s[AK];AQ=AL[AK].from;AP=AL[AK].to}else{AN=s[AO];AQ=AL[AR+"1"];AP=AL[AR+"2"]}}if(AQ!=null&&AP!=null&&AQ>AP){return{from:AP,to:AQ,axis:AN}}return{from:AQ,to:AP,axis:AN}}function S(){var AO;Y.save();Y.translate(e.left,e.top);if(g.grid.backgroundColor){Y.fillStyle=R(g.grid.backgroundColor,t,0,"rgba(255, 255, 255, 0)");Y.fillRect(0,0,I,t)}var AL=g.grid.markings;if(AL){if(C.isFunction(AL)){AL=AL({xmin:s.xaxis.min,xmax:s.xaxis.max,ymin:s.yaxis.min,ymax:s.yaxis.max,xaxis:s.xaxis,yaxis:s.yaxis,x2axis:s.x2axis,y2axis:s.y2axis})}for(AO=0;AO<AL.length;++AO){var AK=AL[AO],AQ=N(AK,"x"),AN=N(AK,"y");if(AQ.from==null){AQ.from=AQ.axis.min}if(AQ.to==null){AQ.to=AQ.axis.max}if(AN.from==null){AN.from=AN.axis.min}if(AN.to==null){AN.to=AN.axis.max}if(AQ.to<AQ.axis.min||AQ.from>AQ.axis.max||AN.to<AN.axis.min||AN.from>AN.axis.max){continue}AQ.from=Math.max(AQ.from,AQ.axis.min);AQ.to=Math.min(AQ.to,AQ.axis.max);AN.from=Math.max(AN.from,AN.axis.min);AN.to=Math.min(AN.to,AN.axis.max);if(AQ.from==AQ.to&&AN.from==AN.to){continue}AQ.from=AQ.axis.p2c(AQ.from);AQ.to=AQ.axis.p2c(AQ.to);AN.from=AN.axis.p2c(AN.from);AN.to=AN.axis.p2c(AN.to);if(AQ.from==AQ.to||AN.from==AN.to){Y.beginPath();Y.strokeStyle=AK.color||g.grid.markingsColor;Y.lineWidth=AK.lineWidth||g.grid.markingsLineWidth;Y.moveTo(AQ.from,AN.from);Y.lineTo(AQ.to,AN.to);Y.stroke()}else{Y.fillStyle=AK.color||g.grid.markingsColor;Y.fillRect(AQ.from,AN.to,AQ.to-AQ.from,AN.from-AN.to)}}}Y.lineWidth=1;Y.strokeStyle=g.grid.tickColor;Y.beginPath();var AM,AP=s.xaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=s.xaxis.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,0);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,t)}AP=s.yaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(0,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}AP=s.x2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,-5);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,5)}AP=s.y2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(I-5,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I+5,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}Y.stroke();if(g.grid.borderWidth){var AR=g.grid.borderWidth;Y.lineWidth=AR;Y.strokeStyle=g.grid.borderColor;Y.strokeRect(-AR/2,-AR/2,I+AR,t+AR)}Y.restore()}function h(){l.find(".tickLabels").remove();var AK=['<div class="tickLabels" style="font-size:smaller;color:'+g.grid.color+'">'];function AM(AP,AQ){for(var AO=0;AO<AP.ticks.length;++AO){var AN=AP.ticks[AO];if(!AN.label||AN.v<AP.min||AN.v>AP.max){continue}AK.push(AQ(AN,AP))}}var AL=g.grid.labelMargin+g.grid.borderWidth;AM(s.xaxis,function(AN,AO){return'<div style="position:absolute;top:'+(e.top+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.yaxis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;right:"+(e.right+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:right" class="tickLabel">'+AN.label+"</div>"});AM(s.x2axis,function(AN,AO){return'<div style="position:absolute;bottom:'+(e.bottom+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.y2axis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;left:"+(e.left+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:left" class="tickLabel">'+AN.label+"</div>"});AK.push("</div>");l.append(AK.join(""))}function AA(AK){if(AK.lines.show){a(AK)}if(AK.bars.show){n(AK)}if(AK.points.show){o(AK)}}function a(AN){function AM(AY,AZ,AR,Ad,Ac){var Ae=AY.points,AS=AY.pointsize,AW=null,AV=null;Y.beginPath();for(var AX=AS;AX<Ae.length;AX+=AS){var AU=Ae[AX-AS],Ab=Ae[AX-AS+1],AT=Ae[AX],Aa=Ae[AX+1];if(AU==null||AT==null){continue}if(Ab<=Aa&&Ab<Ac.min){if(Aa<Ac.min){continue}AU=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(Aa<=Ab&&Aa<Ac.min){if(Ab<Ac.min){continue}AT=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.min}}if(Ab>=Aa&&Ab>Ac.max){if(Aa>Ac.max){continue}AU=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(Aa>=Ab&&Aa>Ac.max){if(Ab>Ac.max){continue}AT=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.max}}if(AU<=AT&&AU<Ad.min){if(AT<Ad.min){continue}Ab=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.min}else{if(AT<=AU&&AT<Ad.min){if(AU<Ad.min){continue}Aa=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.min}}if(AU>=AT&&AU>Ad.max){if(AT>Ad.max){continue}Ab=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.max}else{if(AT>=AU&&AT>Ad.max){if(AU>Ad.max){continue}Aa=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.max}}if(AU!=AW||Ab!=AV){Y.moveTo(Ad.p2c(AU)+AZ,Ac.p2c(Ab)+AR)}AW=AT;AV=Aa;Y.lineTo(Ad.p2c(AT)+AZ,Ac.p2c(Aa)+AR)}Y.stroke()}function AO(AX,Ae,Ac){var Af=AX.points,AR=AX.pointsize,AS=Math.min(Math.max(0,Ac.min),Ac.max),Aa,AV=0,Ad=false;for(var AW=AR;AW<Af.length;AW+=AR){var AU=Af[AW-AR],Ab=Af[AW-AR+1],AT=Af[AW],AZ=Af[AW+1];if(Ad&&AU!=null&&AT==null){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill();Ad=false;continue}if(AU==null||AT==null){continue}if(AU<=AT&&AU<Ae.min){if(AT<Ae.min){continue}Ab=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.min}else{if(AT<=AU&&AT<Ae.min){if(AU<Ae.min){continue}AZ=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.min}}if(AU>=AT&&AU>Ae.max){if(AT>Ae.max){continue}Ab=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.max}else{if(AT>=AU&&AT>Ae.max){if(AU>Ae.max){continue}AZ=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.max}}if(!Ad){Y.beginPath();Y.moveTo(Ae.p2c(AU),Ac.p2c(AS));Ad=true}if(Ab>=Ac.max&&AZ>=Ac.max){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.max));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.max));AV=AT;continue}else{if(Ab<=Ac.min&&AZ<=Ac.min){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.min));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.min));AV=AT;continue}}var Ag=AU,AY=AT;if(Ab<=AZ&&Ab<Ac.min&&AZ>=Ac.min){AU=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(AZ<=Ab&&AZ<Ac.min&&Ab>=Ac.min){AT=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.min}}if(Ab>=AZ&&Ab>Ac.max&&AZ<=Ac.max){AU=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(AZ>=Ab&&AZ>Ac.max&&Ab<=Ac.max){AT=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.max}}if(AU!=Ag){if(Ab<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(Ag),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AU),Ac.p2c(Aa))}Y.lineTo(Ae.p2c(AU),Ac.p2c(Ab));Y.lineTo(Ae.p2c(AT),Ac.p2c(AZ));if(AT!=AY){if(AZ<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(AT),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AY),Ac.p2c(Aa))}AV=Math.max(AT,AY)}if(Ad){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill()}}Y.save();Y.translate(e.left,e.top);Y.lineJoin="round";var AP=AN.lines.lineWidth,AK=AN.shadowSize;if(AP>0&&AK>0){Y.lineWidth=AK;Y.strokeStyle="rgba(0,0,0,0.1)";var AQ=Math.PI/18;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/2),Math.cos(AQ)*(AP/2+AK/2),AN.xaxis,AN.yaxis);Y.lineWidth=AK/2;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/4),Math.cos(AQ)*(AP/2+AK/4),AN.xaxis,AN.yaxis)}Y.lineWidth=AP;Y.strokeStyle=AN.color;var AL=V(AN.lines,AN.color,0,t);if(AL){Y.fillStyle=AL;AO(AN.datapoints,AN.xaxis,AN.yaxis)}if(AP>0){AM(AN.datapoints,0,0,AN.xaxis,AN.yaxis)}Y.restore()}function o(AN){function AP(AU,AT,Ab,AR,AV,AZ,AY){var Aa=AU.points,AQ=AU.pointsize;for(var AS=0;AS<Aa.length;AS+=AQ){var AX=Aa[AS],AW=Aa[AS+1];if(AX==null||AX<AZ.min||AX>AZ.max||AW<AY.min||AW>AY.max){continue}Y.beginPath();Y.arc(AZ.p2c(AX),AY.p2c(AW)+AR,AT,0,AV,false);if(Ab){Y.fillStyle=Ab;Y.fill()}Y.stroke()}}Y.save();Y.translate(e.left,e.top);var AO=AN.lines.lineWidth,AL=AN.shadowSize,AK=AN.points.radius;if(AO>0&&AL>0){var AM=AL/2;Y.lineWidth=AM;Y.strokeStyle="rgba(0,0,0,0.1)";AP(AN.datapoints,AK,null,AM+AM/2,Math.PI,AN.xaxis,AN.yaxis);Y.strokeStyle="rgba(0,0,0,0.2)";AP(AN.datapoints,AK,null,AM/2,Math.PI,AN.xaxis,AN.yaxis)}Y.lineWidth=AO;Y.strokeStyle=AN.color;AP(AN.datapoints,AK,V(AN.points,AN.color),0,2*Math.PI,AN.xaxis,AN.yaxis);Y.restore()}function AB(AV,AU,Ad,AQ,AY,AN,AL,AT,AS,Ac,AZ){var AM,Ab,AR,AX,AO,AK,AW,AP,Aa;if(AZ){AP=AK=AW=true;AO=false;AM=Ad;Ab=AV;AX=AU+AQ;AR=AU+AY;if(Ab<AM){Aa=Ab;Ab=AM;AM=Aa;AO=true;AK=false}}else{AO=AK=AW=true;AP=false;AM=AV+AQ;Ab=AV+AY;AR=Ad;AX=AU;if(AX<AR){Aa=AX;AX=AR;AR=Aa;AP=true;AW=false}}if(Ab<AT.min||AM>AT.max||AX<AS.min||AR>AS.max){return }if(AM<AT.min){AM=AT.min;AO=false}if(Ab>AT.max){Ab=AT.max;AK=false}if(AR<AS.min){AR=AS.min;AP=false}if(AX>AS.max){AX=AS.max;AW=false}AM=AT.p2c(AM);AR=AS.p2c(AR);Ab=AT.p2c(Ab);AX=AS.p2c(AX);if(AL){Ac.beginPath();Ac.moveTo(AM,AR);Ac.lineTo(AM,AX);Ac.lineTo(Ab,AX);Ac.lineTo(Ab,AR);Ac.fillStyle=AL(AR,AX);Ac.fill()}if(AO||AK||AW||AP){Ac.beginPath();Ac.moveTo(AM,AR+AN);if(AO){Ac.lineTo(AM,AX+AN)}else{Ac.moveTo(AM,AX+AN)}if(AW){Ac.lineTo(Ab,AX+AN)}else{Ac.moveTo(Ab,AX+AN)}if(AK){Ac.lineTo(Ab,AR+AN)}else{Ac.moveTo(Ab,AR+AN)}if(AP){Ac.lineTo(AM,AR+AN)}else{Ac.moveTo(AM,AR+AN)}Ac.stroke()}}function n(AM){function AL(AS,AR,AU,AP,AT,AW,AV){var AX=AS.points,AO=AS.pointsize;for(var AQ=0;AQ<AX.length;AQ+=AO){if(AX[AQ]==null){continue}AB(AX[AQ],AX[AQ+1],AX[AQ+2],AR,AU,AP,AT,AW,AV,Y,AM.bars.horizontal)}}Y.save();Y.translate(e.left,e.top);Y.lineWidth=AM.bars.lineWidth;Y.strokeStyle=AM.color;var AK=AM.bars.align=="left"?0:-AM.bars.barWidth/2;var AN=AM.bars.fill?function(AO,AP){return V(AM.bars,AM.color,AO,AP)}:null;AL(AM.datapoints,AK,AK+AM.bars.barWidth,0,AN,AM.xaxis,AM.yaxis);Y.restore()}function V(AM,AK,AL,AO){var AN=AM.fill;if(!AN){return null}if(AM.fillColor){return R(AM.fillColor,AL,AO,AK)}var AP=C.color.parse(AK);AP.a=typeof AN=="number"?AN:0.4;AP.normalize();return AP.toString()}function AI(){l.find(".legend").remove();if(!g.legend.show){return }var AP=[],AN=false,AV=g.legend.labelFormatter,AU,AR;for(i=0;i<O.length;++i){AU=O[i];AR=AU.label;if(!AR){continue}if(i%g.legend.noColumns==0){if(AN){AP.push("</tr>")}AP.push("<tr>");AN=true}if(AV){AR=AV(AR,AU)}AP.push('<td class="legendColorBox"><div style="border:1px solid '+g.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+AU.color+';overflow:hidden"></div></div></td><td class="legendLabel">'+AR+"</td>")}if(AN){AP.push("</tr>")}if(AP.length==0){return }var AT='<table style="font-size:smaller;color:'+g.grid.color+'">'+AP.join("")+"</table>";if(g.legend.container!=null){C(g.legend.container).html(AT)}else{var AQ="",AL=g.legend.position,AM=g.legend.margin;if(AM[0]==null){AM=[AM,AM]}if(AL.charAt(0)=="n"){AQ+="top:"+(AM[1]+e.top)+"px;"}else{if(AL.charAt(0)=="s"){AQ+="bottom:"+(AM[1]+e.bottom)+"px;"}}if(AL.charAt(1)=="e"){AQ+="right:"+(AM[0]+e.right)+"px;"}else{if(AL.charAt(1)=="w"){AQ+="left:"+(AM[0]+e.left)+"px;"}}var AS=C('<div class="legend">'+AT.replace('style="','style="position:absolute;'+AQ+";")+"</div>").appendTo(l);if(g.legend.backgroundOpacity!=0){var AO=g.legend.backgroundColor;if(AO==null){AO=g.grid.backgroundColor;if(AO&&typeof AO=="string"){AO=C.color.parse(AO)}else{AO=C.color.extract(AS,"background-color")}AO.a=1;AO=AO.toString()}var AK=AS.children();C('<div style="position:absolute;width:'+AK.width()+"px;height:"+AK.height()+"px;"+AQ+"background-color:"+AO+';"> </div>').prependTo(AS).css("opacity",g.legend.backgroundOpacity)}}}var w=[],J=null;function AF(AR,AP,AM){var AX=g.grid.mouseActiveRadius,Aj=AX*AX+1,Ah=null,Aa=false,Af,Ad;for(Af=0;Af<O.length;++Af){if(!AM(O[Af])){continue}var AY=O[Af],AQ=AY.xaxis,AO=AY.yaxis,Ae=AY.datapoints.points,Ac=AY.datapoints.pointsize,AZ=AQ.c2p(AR),AW=AO.c2p(AP),AL=AX/AQ.scale,AK=AX/AO.scale;if(AY.lines.show||AY.points.show){for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1];if(AT==null){continue}if(AT-AZ>AL||AT-AZ<-AL||AS-AW>AK||AS-AW<-AK){continue}var AV=Math.abs(AQ.p2c(AT)-AR),AU=Math.abs(AO.p2c(AS)-AP),Ab=AV*AV+AU*AU;if(Ab<=Aj){Aj=Ab;Ah=[Af,Ad/Ac]}}}if(AY.bars.show&&!Ah){var AN=AY.bars.align=="left"?0:-AY.bars.barWidth/2,Ag=AN+AY.bars.barWidth;for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1],Ai=Ae[Ad+2];if(AT==null){continue}if(O[Af].bars.horizontal?(AZ<=Math.max(Ai,AT)&&AZ>=Math.min(Ai,AT)&&AW>=AS+AN&&AW<=AS+Ag):(AZ>=AT+AN&&AZ<=AT+Ag&&AW>=Math.min(Ai,AS)&&AW<=Math.max(Ai,AS))){Ah=[Af,Ad/Ac]}}}}if(Ah){Af=Ah[0];Ad=Ah[1];Ac=O[Af].datapoints.pointsize;return{datapoint:O[Af].datapoints.points.slice(Ad*Ac,(Ad+1)*Ac),dataIndex:Ad,series:O[Af],seriesIndex:Af}}return null}function D(AK){if(g.grid.hoverable){H("plothover",AK,function(AL){return AL.hoverable!=false})}}function d(AK){H("plotclick",AK,function(AL){return AL.clickable!=false})}function H(AL,AK,AM){var AN=AD.offset(),AS={pageX:AK.pageX,pageY:AK.pageY},AQ=AK.pageX-AN.left-e.left,AO=AK.pageY-AN.top-e.top;if(s.xaxis.used){AS.x=s.xaxis.c2p(AQ)}if(s.yaxis.used){AS.y=s.yaxis.c2p(AO)}if(s.x2axis.used){AS.x2=s.x2axis.c2p(AQ)}if(s.y2axis.used){AS.y2=s.y2axis.c2p(AO)}var AT=AF(AQ,AO,AM);if(AT){AT.pageX=parseInt(AT.series.xaxis.p2c(AT.datapoint[0])+AN.left+e.left);AT.pageY=parseInt(AT.series.yaxis.p2c(AT.datapoint[1])+AN.top+e.top)}if(g.grid.autoHighlight){for(var AP=0;AP<w.length;++AP){var AR=w[AP];if(AR.auto==AL&&!(AT&&AR.series==AT.series&&AR.point==AT.datapoint)){x(AR.series,AR.point)}}if(AT){AE(AT.series,AT.datapoint,AL)}}l.trigger(AL,[AS,AT])}function q(){if(!J){J=setTimeout(v,30)}}function v(){J=null;AJ.save();AJ.clearRect(0,0,y,Q);AJ.translate(e.left,e.top);var AL,AK;for(AL=0;AL<w.length;++AL){AK=w[AL];if(AK.series.bars.show){z(AK.series,AK.point)}else{u(AK.series,AK.point)}}AJ.restore();Z(L.drawOverlay,[AJ])}function AE(AM,AK,AN){if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL==-1){w.push({series:AM,point:AK,auto:AN});q()}else{if(!AN){w[AL].auto=false}}}function x(AM,AK){if(AM==null&&AK==null){w=[];q()}if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL!=-1){w.splice(AL,1);q()}}function j(AM,AN){for(var AK=0;AK<w.length;++AK){var AL=w[AK];if(AL.series==AM&&AL.point[0]==AN[0]&&AL.point[1]==AN[1]){return AK}}return -1}function u(AN,AM){var AL=AM[0],AR=AM[1],AQ=AN.xaxis,AP=AN.yaxis;if(AL<AQ.min||AL>AQ.max||AR<AP.min||AR>AP.max){return }var AO=AN.points.radius+AN.points.lineWidth/2;AJ.lineWidth=AO;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AK=1.5*AO;AJ.beginPath();AJ.arc(AQ.p2c(AL),AP.p2c(AR),AK,0,2*Math.PI,false);AJ.stroke()}function z(AN,AK){AJ.lineWidth=AN.bars.lineWidth;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AM=C.color.parse(AN.color).scale("a",0.5).toString();var AL=AN.bars.align=="left"?0:-AN.bars.barWidth/2;AB(AK[0],AK[1],AK[2]||0,AL,AL+AN.bars.barWidth,0,function(){return AM},AN.xaxis,AN.yaxis,AJ,AN.bars.horizontal)}function R(AM,AL,AQ,AO){if(typeof AM=="string"){return AM}else{var AP=Y.createLinearGradient(0,AQ,0,AL);for(var AN=0,AK=AM.colors.length;AN<AK;++AN){var AR=AM.colors[AN];if(typeof AR!="string"){AR=C.color.parse(AO).scale("rgb",AR.brightness);AR.a*=AR.opacity;AR=AR.toString()}AP.addColorStop(AN/(AK-1),AR)}return AP}}}C.plot=function(G,E,D){var F=new B(C(G),E,D,C.plot.plugins);return F};C.plot.plugins=[];C.plot.formatDate=function(H,E,G){var L=function(N){N=""+N;return N.length==1?"0"+N:N};var D=[];var M=false;var K=H.getUTCHours();var I=K<12;if(G==null){G=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}if(E.search(/%p|%P/)!=-1){if(K>12){K=K-12}else{if(K==0){K=12}}}for(var F=0;F<E.length;++F){var J=E.charAt(F);if(M){switch(J){case"h":J=""+K;break;case"H":J=L(K);break;case"M":J=L(H.getUTCMinutes());break;case"S":J=L(H.getUTCSeconds());break;case"d":J=""+H.getUTCDate();break;case"m":J=""+(H.getUTCMonth()+1);break;case"y":J=""+H.getUTCFullYear();break;case"b":J=""+G[H.getUTCMonth()];break;case"p":J=(I)?("am"):("pm");break;case"P":J=(I)?("AM"):("PM");break}D.push(J);M=false}else{if(J=="%"){M=true}else{D.push(J)}}}return D.join("")};function A(E,D){return D*Math.floor(E/D)}})(jQuery);
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.navigate.js
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
-Flot plugin for adding panning and zooming capabilities to a plot.
-
-The default behaviour is double click and scrollwheel up/down to zoom
-in, drag to pan. The plugin defines plot.zoom({ center }),
-plot.zoomOut() and plot.pan(offset) so you easily can add custom
-controls. It also fires a "plotpan" and "plotzoom" event when
-something happens, useful for synchronizing plots.
-
-Example usage:
-
-  plot = $.plot(...);
-  
-  // zoom default amount in on the pixel (100, 200) 
-  plot.zoom({ center: { left: 10, top: 20 } });
-
-  // zoom out again
-  plot.zoomOut({ center: { left: 10, top: 20 } });
-
-  // pan 100 pixels to the left and 20 down
-  plot.pan({ left: -100, top: 20 })
-
-
-Options:
-
-  zoom: {
-    interactive: false
-    trigger: "dblclick" // or "click" for single click
-    amount: 1.5         // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
-  }
-  
-  pan: {
-    interactive: false
-  }
-
-  xaxis, yaxis, x2axis, y2axis: {
-    zoomRange: null  // or [number, number] (min range, max range)
-    panRange: null   // or [number, number] (min, max)
-  }
-  
-"interactive" enables the built-in drag/click behaviour. "amount" is
-the amount to zoom the viewport relative to the current range, so 1 is
-100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is 70% (zoom out).
-
-"zoomRange" is the interval in which zooming can happen, e.g. with
-zoomRange: [1, 100] the zoom will never scale the axis so that the
-difference between min and max is smaller than 1 or larger than 100.
-You can set either of them to null to ignore.
-
-"panRange" confines the panning to stay within a range, e.g. with
-panRange: [-10, 20] panning stops at -10 in one end and at 20 in the
-other. Either can be null.
-*/
-
-
-// First two dependencies, jquery.event.drag.js and
-// jquery.mousewheel.js, we put them inline here to save people the
-// effort of downloading them.
-
-/*
-jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)  
-Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
-*/
-(function(E){E.fn.drag=function(L,K,J){if(K){this.bind("dragstart",L)}if(J){this.bind("dragend",J)}return !L?this.trigger("drag"):this.bind("drag",K?K:L)};var A=E.event,B=A.special,F=B.drag={not:":input",distance:0,which:1,dragging:false,setup:function(J){J=E.extend({distance:F.distance,which:F.which,not:F.not},J||{});J.distance=I(J.distance);A.add(this,"mousedown",H,J);if(this.attachEvent){this.attachEvent("ondragstart",D)}},teardown:function(){A.remove(this,"mousedown",H);if(this===F.dragging){F.dragging=F.proxy=false}G(this,true);if(this.detachEvent){this.detachEvent("ondragstart",D)}}};B.dragstart=B.dragend={setup:function(){},teardown:function(){}};function H(L){var K=this,J,M=L.data||{};if(M.elem){K=L.dragTarget=M.elem;L.dragProxy=F.proxy||K;L.cursorOffsetX=M.pageX-M.left;L.cursorOffsetY=M.pageY-M.top;L.offsetX=L.pageX-L.cursorOffsetX;L.offsetY=L.pageY-L.cursorOffsetY}else{if(F.dragging||(M.which>0&&L.which!=M.which)||E(L.target).is(M.not)){return }}switch(L.type){case"mousedown":E.extend(M,E(K).offset(),{elem:K,target:L.target,pageX:L.pageX,pageY:L.pageY});A.add(document,"mousemove mouseup",H,M);G(K,false);F.dragging=null;return false;case !F.dragging&&"mousemove":if(I(L.pageX-M.pageX)+I(L.pageY-M.pageY)<M.distance){break}L.target=M.target;J=C(L,"dragstart",K);if(J!==false){F.dragging=K;F.proxy=L.dragProxy=E(J||K)[0]}case"mousemove":if(F.dragging){J=C(L,"drag",K);if(B.drop){B.drop.allowed=(J!==false);B.drop.handler(L)}if(J!==false){break}L.type="mouseup"}case"mouseup":A.remove(document,"mousemove mouseup",H);if(F.dragging){if(B.drop){B.drop.handler(L)}C(L,"dragend",K)}G(K,true);F.dragging=F.proxy=M.elem=false;break}return true}function C(M,K,L){M.type=K;var J=E.event.handle.call(L,M);return J===false?false:J||M.result}function I(J){return Math.pow(J,2)}function D(){return(F.dragging===false)}function G(K,J){if(!K){return }K.unselectable=J?"off":"on";K.onselectstart=function(){return J};if(K.style){K.style.MozUserSelect=J?"":"none"}}})(jQuery);
-
-
-/* jquery.mousewheel.min.js
- * Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
- * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
- * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
- * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
- * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
- *
- * Version: 3.0.2
- * 
- * Requires: 1.2.2+
- */
-(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);
-
-
-
-
-(function ($) {
-    var options = {
-        xaxis: {
-            zoomRange: null, // or [number, number] (min range, max range)
-            panRange: null // or [number, number] (min, max)
-        },
-        zoom: {
-            interactive: false,
-            trigger: "dblclick", // or "click" for single click
-            amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
-        },
-        pan: {
-            interactive: false
-        }
-    };
-
-    function init(plot) {
-        function bindEvents(plot, eventHolder) {
-            var o = plot.getOptions();
-            if (o.zoom.interactive) {
-                function clickHandler(e, zoomOut) {
-                    var c = plot.offset();
-                    c.left = e.pageX - c.left;
-                    c.top = e.pageY - c.top;
-                    if (zoomOut)
-                        plot.zoomOut({ center: c });
-                    else
-                        plot.zoom({ center: c });
-                }
-                
-                eventHolder[o.zoom.trigger](clickHandler);
-
-                eventHolder.mousewheel(function (e, delta) {
-                    clickHandler(e, delta < 0);
-                    return false;
-                });
-            }
-            if (o.pan.interactive) {
-                var prevCursor = 'default', pageX = 0, pageY = 0;
-                
-                eventHolder.bind("dragstart", { distance: 10 }, function (e) {
-                    if (e.which != 1)  // only accept left-click
-                        return false;
-                    eventHolderCursor = eventHolder.css('cursor');
-                    eventHolder.css('cursor', 'move');
-                    pageX = e.pageX;
-                    pageY = e.pageY;
-                });
-                eventHolder.bind("drag", function (e) {
-                    // unused at the moment, but we need it here to
-                    // trigger the dragstart/dragend events
-                });
-                eventHolder.bind("dragend", function (e) {
-                    eventHolder.css('cursor', prevCursor);
-                    plot.pan({ left: pageX - e.pageX,
-                               top: pageY - e.pageY });
-                });
-            }
-        }
-
-        plot.zoomOut = function (args) {
-            if (!args)
-                args = {};
-            
-            if (!args.amount)
-                args.amount = plot.getOptions().zoom.amount
-
-            args.amount = 1 / args.amount;
-            plot.zoom(args);
-        }
-        
-        plot.zoom = function (args) {
-            if (!args)
-                args = {};
-            
-            var axes = plot.getAxes(),
-                options = plot.getOptions(),
-                c = args.center,
-                amount = args.amount ? args.amount : options.zoom.amount,
-                w = plot.width(), h = plot.height();
-
-            if (!c)
-                c = { left: w / 2, top: h / 2 };
-                
-            var xf = c.left / w,
-                x1 = c.left - xf * w / amount,
-                x2 = c.left + (1 - xf) * w / amount,
-                yf = c.top / h,
-                y1 = c.top - yf * h / amount,
-                y2 = c.top + (1 - yf) * h / amount;
-
-            function scaleAxis(min, max, name) {
-                var axis = axes[name],
-                    axisOptions = options[name];
-                
-                if (!axis.used)
-                    return;
-                    
-                min = axis.c2p(min);
-                max = axis.c2p(max);
-                if (max < min) { // make sure min < max
-                    var tmp = min
-                    min = max;
-                    max = tmp;
-                }
-
-                var range = max - min, zr = axisOptions.zoomRange;
-                if (zr &&
-                    ((zr[0] != null && range < zr[0]) ||
-                     (zr[1] != null && range > zr[1])))
-                    return;
-            
-                axisOptions.min = min;
-                axisOptions.max = max;
-            }
-
-            scaleAxis(x1, x2, 'xaxis');
-            scaleAxis(x1, x2, 'x2axis');
-            scaleAxis(y1, y2, 'yaxis');
-            scaleAxis(y1, y2, 'y2axis');
-            
-            plot.setupGrid();
-            plot.draw();
-            
-            if (!args.preventEvent)
-                plot.getPlaceholder().trigger("plotzoom", [ plot ]);
-        }
-
-        plot.pan = function (args) {
-            var l = +args.left, t = +args.top,
-                axes = plot.getAxes(), options = plot.getOptions();
-
-            if (isNaN(l))
-                l = 0;
-            if (isNaN(t))
-                t = 0;
-
-            function panAxis(delta, name) {
-                var axis = axes[name],
-                    axisOptions = options[name],
-                    min, max;
-                
-                if (!axis.used)
-                    return;
-
-                min = axis.c2p(axis.p2c(axis.min) + delta),
-                max = axis.c2p(axis.p2c(axis.max) + delta);
-
-                var pr = axisOptions.panRange;
-                if (pr) {
-                    // check whether we hit the wall
-                    if (pr[0] != null && pr[0] > min) {
-                        delta = pr[0] - min;
-                        min += delta;
-                        max += delta;
-                    }
-                    
-                    if (pr[1] != null && pr[1] < max) {
-                        delta = pr[1] - max;
-                        min += delta;
-                        max += delta;
-                    }
-                }
-                
-                axisOptions.min = min;
-                axisOptions.max = max;
-            }
-
-            panAxis(l, 'xaxis');
-            panAxis(l, 'x2axis');
-            panAxis(t, 'yaxis');
-            panAxis(t, 'y2axis');
-            
-            plot.setupGrid();
-            plot.draw();
-            
-            if (!args.preventEvent)
-                plot.getPlaceholder().trigger("plotpan", [ plot ]);
-        }
-        
-        plot.hooks.bindEvents.push(bindEvents);
-    }
-    
-    $.plot.plugins.push({
-        init: init,
-        options: options,
-        name: 'navigate',
-        version: '1.1'
-    });
-})(jQuery);
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.navigate.min.js
+++ /dev/null
@@ -1,1 +0,0 @@
-(function(R){R.fn.drag=function(A,B,C){if(B){this.bind("dragstart",A)}if(C){this.bind("dragend",C)}return !A?this.trigger("drag"):this.bind("drag",B?B:A)};var M=R.event,L=M.special,Q=L.drag={not:":input",distance:0,which:1,dragging:false,setup:function(A){A=R.extend({distance:Q.distance,which:Q.which,not:Q.not},A||{});A.distance=N(A.distance);M.add(this,"mousedown",O,A);if(this.attachEvent){this.attachEvent("ondragstart",J)}},teardown:function(){M.remove(this,"mousedown",O);if(this===Q.dragging){Q.dragging=Q.proxy=false}P(this,true);if(this.detachEvent){this.detachEvent("ondragstart",J)}}};L.dragstart=L.dragend={setup:function(){},teardown:function(){}};function O(A){var B=this,C,D=A.data||{};if(D.elem){B=A.dragTarget=D.elem;A.dragProxy=Q.proxy||B;A.cursorOffsetX=D.pageX-D.left;A.cursorOffsetY=D.pageY-D.top;A.offsetX=A.pageX-A.cursorOffsetX;A.offsetY=A.pageY-A.cursorOffsetY}else{if(Q.dragging||(D.which>0&&A.which!=D.which)||R(A.target).is(D.not)){return }}switch(A.type){case"mousedown":R.extend(D,R(B).offset(),{elem:B,target:A.target,pageX:A.pageX,pageY:A.pageY});M.add(document,"mousemove mouseup",O,D);P(B,false);Q.dragging=null;return false;case !Q.dragging&&"mousemove":if(N(A.pageX-D.pageX)+N(A.pageY-D.pageY)<D.distance){break}A.target=D.target;C=K(A,"dragstart",B);if(C!==false){Q.dragging=B;Q.proxy=A.dragProxy=R(C||B)[0]}case"mousemove":if(Q.dragging){C=K(A,"drag",B);if(L.drop){L.drop.allowed=(C!==false);L.drop.handler(A)}if(C!==false){break}A.type="mouseup"}case"mouseup":M.remove(document,"mousemove mouseup",O);if(Q.dragging){if(L.drop){L.drop.handler(A)}K(A,"dragend",B)}P(B,true);Q.dragging=Q.proxy=D.elem=false;break}return true}function K(D,B,A){D.type=B;var C=R.event.handle.call(A,D);return C===false?false:C||D.result}function N(A){return Math.pow(A,2)}function J(){return(Q.dragging===false)}function P(A,B){if(!A){return }A.unselectable=B?"off":"on";A.onselectstart=function(){return B};if(A.style){A.style.MozUserSelect=B?"":"none"}}})(jQuery);(function(C){var B=["DOMMouseScroll","mousewheel"];C.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var D=B.length;D;){this.addEventListener(B[--D],A,false)}}else{this.onmousewheel=A}},teardown:function(){if(this.removeEventListener){for(var D=B.length;D;){this.removeEventListener(B[--D],A,false)}}else{this.onmousewheel=null}}};C.fn.extend({mousewheel:function(D){return D?this.bind("mousewheel",D):this.trigger("mousewheel")},unmousewheel:function(D){return this.unbind("mousewheel",D)}});function A(E){var G=[].slice.call(arguments,1),D=0,F=true;E=C.event.fix(E||window.event);E.type="mousewheel";if(E.wheelDelta){D=E.wheelDelta/120}if(E.detail){D=-E.detail/3}G.unshift(E,D);return C.event.handle.apply(this,G)}})(jQuery);(function(B){var A={xaxis:{zoomRange:null,panRange:null},zoom:{interactive:false,trigger:"dblclick",amount:1.5},pan:{interactive:false}};function C(D){function E(J,F){var K=J.getOptions();if(K.zoom.interactive){function L(N,M){var O=J.offset();O.left=N.pageX-O.left;O.top=N.pageY-O.top;if(M){J.zoomOut({center:O})}else{J.zoom({center:O})}}F[K.zoom.trigger](L);F.mousewheel(function(M,N){L(M,N<0);return false})}if(K.pan.interactive){var I="default",H=0,G=0;F.bind("dragstart",{distance:10},function(M){if(M.which!=1){return false}eventHolderCursor=F.css("cursor");F.css("cursor","move");H=M.pageX;G=M.pageY});F.bind("drag",function(M){});F.bind("dragend",function(M){F.css("cursor",I);J.pan({left:H-M.pageX,top:G-M.pageY})})}}D.zoomOut=function(F){if(!F){F={}}if(!F.amount){F.amount=D.getOptions().zoom.amount}F.amount=1/F.amount;D.zoom(F)};D.zoom=function(M){if(!M){M={}}var L=D.getAxes(),S=D.getOptions(),N=M.center,J=M.amount?M.amount:S.zoom.amount,R=D.width(),I=D.height();if(!N){N={left:R/2,top:I/2}}var Q=N.left/R,G=N.left-Q*R/J,F=N.left+(1-Q)*R/J,H=N.top/I,P=N.top-H*I/J,O=N.top+(1-H)*I/J;function K(X,T,V){var Y=L[V],a=S[V];if(!Y.used){return }X=Y.c2p(X);T=Y.c2p(T);if(T<X){var W=X;X=T;T=W}var U=T-X,Z=a.zoomRange;if(Z&&((Z[0]!=null&&U<Z[0])||(Z[1]!=null&&U>Z[1]))){return }a.min=X;a.max=T}K(G,F,"xaxis");K(G,F,"x2axis");K(P,O,"yaxis");K(P,O,"y2axis");D.setupGrid();D.draw();if(!M.preventEvent){D.getPlaceholder().trigger("plotzoom",[D])}};D.pan=function(I){var F=+I.left,J=+I.top,K=D.getAxes(),H=D.getOptions();if(isNaN(F)){F=0}if(isNaN(J)){J=0}function G(R,M){var O=K[M],Q=H[M],N,L;if(!O.used){return }N=O.c2p(O.p2c(O.min)+R),L=O.c2p(O.p2c(O.max)+R);var P=Q.panRange;if(P){if(P[0]!=null&&P[0]>N){R=P[0]-N;N+=R;L+=R}if(P[1]!=null&&P[1]<L){R=P[1]-L;N+=R;L+=R}}Q.min=N;Q.max=L}G(F,"xaxis");G(F,"x2axis");G(J,"yaxis");G(J,"y2axis");D.setupGrid();D.draw();if(!I.preventEvent){D.getPlaceholder().trigger("plotpan",[D])}};D.hooks.bindEvents.push(E)}B.plot.plugins.push({init:C,options:A,name:"navigate",version:"1.1"})})(jQuery);
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.selection.js
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
-Flot plugin for selecting regions.
-
-The plugin defines the following options:
-
-  selection: {
-    mode: null or "x" or "y" or "xy",
-    color: color
-  }
-
-You enable selection support by setting the mode to one of "x", "y" or
-"xy". In "x" mode, the user will only be able to specify the x range,
-similarly for "y" mode. For "xy", the selection becomes a rectangle
-where both ranges can be specified. "color" is color of the selection.
-
-When selection support is enabled, a "plotselected" event will be emitted
-on the DOM element you passed into the plot function. The event
-handler gets one extra parameter with the ranges selected on the axes,
-like this:
-
-  placeholder.bind("plotselected", function(event, ranges) {
-    alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
-    // similar for yaxis, secondary axes are in x2axis
-    // and y2axis if present
-  });
-
-The "plotselected" event is only fired when the user has finished
-making the selection. A "plotselecting" event is fired during the
-process with the same parameters as the "plotselected" event, in case
-you want to know what's happening while it's happening,
-
-A "plotunselected" event with no arguments is emitted when the user
-clicks the mouse to remove the selection.
-
-The plugin allso adds the following methods to the plot object:
-
-- setSelection(ranges, preventEvent)
-
-  Set the selection rectangle. The passed in ranges is on the same
-  form as returned in the "plotselected" event. If the selection
-  mode is "x", you should put in either an xaxis (or x2axis) object,
-  if the mode is "y" you need to put in an yaxis (or y2axis) object
-  and both xaxis/x2axis and yaxis/y2axis if the selection mode is
-  "xy", like this:
-
-    setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
-
-  setSelection will trigger the "plotselected" event when called. If
-  you don't want that to happen, e.g. if you're inside a
-  "plotselected" handler, pass true as the second parameter.
-  
-- clearSelection(preventEvent)
-
-  Clear the selection rectangle. Pass in true to avoid getting a
-  "plotunselected" event.
-
-- getSelection()
-
-  Returns the current selection in the same format as the
-  "plotselected" event. If there's currently no selection, the
-  function returns null.
-
-*/
-
-(function ($) {
-    function init(plot) {
-        var selection = {
-                first: { x: -1, y: -1}, second: { x: -1, y: -1},
-                show: false,
-                active: false
-            };
-
-        // FIXME: The drag handling implemented here should be
-        // abstracted out, there's some similar code from a library in
-        // the navigation plugin, this should be massaged a bit to fit
-        // the Flot cases here better and reused. Doing this would
-        // make this plugin much slimmer.
-        var savedhandlers = {};
-
-        function onMouseMove(e) {
-            if (selection.active) {
-                plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
-
-                updateSelection(e);
-            }
-        }
-
-        function onMouseDown(e) {
-            if (e.which != 1)  // only accept left-click
-                return;
-            
-            // cancel out any text selections
-            document.body.focus();
-
-            // prevent text selection and drag in old-school browsers
-            if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
-                savedhandlers.onselectstart = document.onselectstart;
-                document.onselectstart = function () { return false; };
-            }
-            if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
-                savedhandlers.ondrag = document.ondrag;
-                document.ondrag = function () { return false; };
-            }
-
-            setSelectionPos(selection.first, e);
-
-            selection.active = true;
-            
-            $(document).one("mouseup", onMouseUp);
-        }
-
-        function onMouseUp(e) {
-            // revert drag stuff for old-school browsers
-            if (document.onselectstart !== undefined)
-                document.onselectstart = savedhandlers.onselectstart;
-            if (document.ondrag !== undefined)
-                document.ondrag = savedhandlers.ondrag;
-
-            // no more draggy-dee-drag
-            selection.active = false;
-            updateSelection(e);
-
-            if (selectionIsSane())
-                triggerSelectedEvent();
-            else {
-                // this counts as a clear
-                plot.getPlaceholder().trigger("plotunselected", [ ]);
-                plot.getPlaceholder().trigger("plotselecting", [ null ]);
-            }
-
-            return false;
-        }
-
-        function getSelection() {
-            if (!selectionIsSane())
-                return null;
-
-            var x1 = Math.min(selection.first.x, selection.second.x),
-                x2 = Math.max(selection.first.x, selection.second.x),
-                y1 = Math.max(selection.first.y, selection.second.y),
-                y2 = Math.min(selection.first.y, selection.second.y);
-
-            var r = {};
-            var axes = plot.getAxes();
-            if (axes.xaxis.used)
-                r.xaxis = { from: axes.xaxis.c2p(x1), to: axes.xaxis.c2p(x2) };
-            if (axes.x2axis.used)
-                r.x2axis = { from: axes.x2axis.c2p(x1), to: axes.x2axis.c2p(x2) };
-            if (axes.yaxis.used)
-                r.yaxis = { from: axes.yaxis.c2p(y1), to: axes.yaxis.c2p(y2) };
-            if (axes.y2axis.used)
-                r.y2axis = { from: axes.y2axis.c2p(y1), to: axes.y2axis.c2p(y2) };
-            return r;
-        }
-
-        function triggerSelectedEvent() {
-            var r = getSelection();
-
-            plot.getPlaceholder().trigger("plotselected", [ r ]);
-
-            // backwards-compat stuff, to be removed in future
-            var axes = plot.getAxes();
-            if (axes.xaxis.used && axes.yaxis.used)
-                plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
-        }
-
-        function clamp(min, value, max) {
-            return value < min? min: (value > max? max: value);
-        }
-
-        function setSelectionPos(pos, e) {
-            var o = plot.getOptions();
-            var offset = plot.getPlaceholder().offset();
-            var plotOffset = plot.getPlotOffset();
-            pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
-            pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
-
-            if (o.selection.mode == "y")
-                pos.x = pos == selection.first? 0: plot.width();
-
-            if (o.selection.mode == "x")
-                pos.y = pos == selection.first? 0: plot.height();
-        }
-
-        function updateSelection(pos) {
-            if (pos.pageX == null)
-                return;
-
-            setSelectionPos(selection.second, pos);
-            if (selectionIsSane()) {
-                selection.show = true;
-                plot.triggerRedrawOverlay();
-            }
-            else
-                clearSelection(true);
-        }
-
-        function clearSelection(preventEvent) {
-            if (selection.show) {
-                selection.show = false;
-                plot.triggerRedrawOverlay();
-                if (!preventEvent)
-                    plot.getPlaceholder().trigger("plotunselected", [ ]);
-            }
-        }
-
-        function setSelection(ranges, preventEvent) {
-            var axis, range, axes = plot.getAxes();
-            var o = plot.getOptions();
-
-            if (o.selection.mode == "y") {
-                selection.first.x = 0;
-                selection.second.x = plot.width();
-            }
-            else {
-                axis = ranges["xaxis"]? axes["xaxis"]: (ranges["x2axis"]? axes["x2axis"]: axes["xaxis"]);
-                range = ranges["xaxis"] || ranges["x2axis"] || { from:ranges["x1"], to:ranges["x2"] }
-                selection.first.x = axis.p2c(Math.min(range.from, range.to));
-                selection.second.x = axis.p2c(Math.max(range.from, range.to));
-            }
-
-            if (o.selection.mode == "x") {
-                selection.first.y = 0;
-                selection.second.y = plot.height();
-            }
-            else {
-                axis = ranges["yaxis"]? axes["yaxis"]: (ranges["y2axis"]? axes["y2axis"]: axes["yaxis"]);
-                range = ranges["yaxis"] || ranges["y2axis"] || { from:ranges["y1"], to:ranges["y2"] }
-                selection.first.y = axis.p2c(Math.min(range.from, range.to));
-                selection.second.y = axis.p2c(Math.max(range.from, range.to));
-            }
-
-            selection.show = true;
-            plot.triggerRedrawOverlay();
-            if (!preventEvent)
-                triggerSelectedEvent();
-        }
-
-        function selectionIsSane() {
-            var minSize = 5;
-            return Math.abs(selection.second.x - selection.first.x) >= minSize &&
-                Math.abs(selection.second.y - selection.first.y) >= minSize;
-        }
-
-        plot.clearSelection = clearSelection;
-        plot.setSelection = setSelection;
-        plot.getSelection = getSelection;
-
-        plot.hooks.bindEvents.push(function(plot, eventHolder) {
-            var o = plot.getOptions();
-            if (o.selection.mode != null)
-                eventHolder.mousemove(onMouseMove);
-
-            if (o.selection.mode != null)
-                eventHolder.mousedown(onMouseDown);
-        });
-
-
-        plot.hooks.drawOverlay.push(function (plot, ctx) {
-            // draw selection
-            if (selection.show && selectionIsSane()) {
-                var plotOffset = plot.getPlotOffset();
-                var o = plot.getOptions();
-
-                ctx.save();
-                ctx.translate(plotOffset.left, plotOffset.top);
-
-                var c = $.color.parse(o.selection.color);
-
-                ctx.strokeStyle = c.scale('a', 0.8).toString();
-                ctx.lineWidth = 1;
-                ctx.lineJoin = "round";
-                ctx.fillStyle = c.scale('a', 0.4).toString();
-
-                var x = Math.min(selection.first.x, selection.second.x),
-                    y = Math.min(selection.first.y, selection.second.y),
-                    w = Math.abs(selection.second.x - selection.first.x),
-                    h = Math.abs(selection.second.y - selection.first.y);
-
-                ctx.fillRect(x, y, w, h);
-                ctx.strokeRect(x, y, w, h);
-
-                ctx.restore();
-            }
-        });
-    }
-
-    $.plot.plugins.push({
-        init: init,
-        options: {
-            selection: {
-                mode: null, // one of null, "x", "y" or "xy"
-                color: "#e8cfac"
-            }
-        },
-        name: 'selection',
-        version: '1.0'
-    });
-})(jQuery);
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.selection.min.js
+++ /dev/null
@@ -1,1 +0,0 @@
-(function(A){function B(J){var O={first:{x:-1,y:-1},second:{x:-1,y:-1},show:false,active:false};var L={};function D(Q){if(O.active){J.getPlaceholder().trigger("plotselecting",[F()]);K(Q)}}function M(Q){if(Q.which!=1){return }document.body.focus();if(document.onselectstart!==undefined&&L.onselectstart==null){L.onselectstart=document.onselectstart;document.onselectstart=function(){return false}}if(document.ondrag!==undefined&&L.ondrag==null){L.ondrag=document.ondrag;document.ondrag=function(){return false}}C(O.first,Q);O.active=true;A(document).one("mouseup",I)}function I(Q){if(document.onselectstart!==undefined){document.onselectstart=L.onselectstart}if(document.ondrag!==undefined){document.ondrag=L.ondrag}O.active=false;K(Q);if(E()){H()}else{J.getPlaceholder().trigger("plotunselected",[]);J.getPlaceholder().trigger("plotselecting",[null])}return false}function F(){if(!E()){return null}var R=Math.min(O.first.x,O.second.x),Q=Math.max(O.first.x,O.second.x),T=Math.max(O.first.y,O.second.y),S=Math.min(O.first.y,O.second.y);var U={};var V=J.getAxes();if(V.xaxis.used){U.xaxis={from:V.xaxis.c2p(R),to:V.xaxis.c2p(Q)}}if(V.x2axis.used){U.x2axis={from:V.x2axis.c2p(R),to:V.x2axis.c2p(Q)}}if(V.yaxis.used){U.yaxis={from:V.yaxis.c2p(T),to:V.yaxis.c2p(S)}}if(V.y2axis.used){U.y2axis={from:V.y2axis.c2p(T),to:V.y2axis.c2p(S)}}return U}function H(){var Q=F();J.getPlaceholder().trigger("plotselected",[Q]);var R=J.getAxes();if(R.xaxis.used&&R.yaxis.used){J.getPlaceholder().trigger("selected",[{x1:Q.xaxis.from,y1:Q.yaxis.from,x2:Q.xaxis.to,y2:Q.yaxis.to}])}}function G(R,S,Q){return S<R?R:(S>Q?Q:S)}function C(U,R){var T=J.getOptions();var S=J.getPlaceholder().offset();var Q=J.getPlotOffset();U.x=G(0,R.pageX-S.left-Q.left,J.width());U.y=G(0,R.pageY-S.top-Q.top,J.height());if(T.selection.mode=="y"){U.x=U==O.first?0:J.width()}if(T.selection.mode=="x"){U.y=U==O.first?0:J.height()}}function K(Q){if(Q.pageX==null){return }C(O.second,Q);if(E()){O.show=true;J.triggerRedrawOverlay()}else{P(true)}}function P(Q){if(O.show){O.show=false;J.triggerRedrawOverlay();if(!Q){J.getPlaceholder().trigger("plotunselected",[])}}}function N(R,Q){var T,S,U=J.getAxes();var V=J.getOptions();if(V.selection.mode=="y"){O.first.x=0;O.second.x=J.width()}else{T=R.xaxis?U.xaxis:(R.x2axis?U.x2axis:U.xaxis);S=R.xaxis||R.x2axis||{from:R.x1,to:R.x2};O.first.x=T.p2c(Math.min(S.from,S.to));O.second.x=T.p2c(Math.max(S.from,S.to))}if(V.selection.mode=="x"){O.first.y=0;O.second.y=J.height()}else{T=R.yaxis?U.yaxis:(R.y2axis?U.y2axis:U.yaxis);S=R.yaxis||R.y2axis||{from:R.y1,to:R.y2};O.first.y=T.p2c(Math.min(S.from,S.to));O.second.y=T.p2c(Math.max(S.from,S.to))}O.show=true;J.triggerRedrawOverlay();if(!Q){H()}}function E(){var Q=5;return Math.abs(O.second.x-O.first.x)>=Q&&Math.abs(O.second.y-O.first.y)>=Q}J.clearSelection=P;J.setSelection=N;J.getSelection=F;J.hooks.bindEvents.push(function(R,Q){var S=R.getOptions();if(S.selection.mode!=null){Q.mousemove(D)}if(S.selection.mode!=null){Q.mousedown(M)}});J.hooks.drawOverlay.push(function(T,Y){if(O.show&&E()){var R=T.getPlotOffset();var Q=T.getOptions();Y.save();Y.translate(R.left,R.top);var U=A.color.parse(Q.selection.color);Y.strokeStyle=U.scale("a",0.8).toString();Y.lineWidth=1;Y.lineJoin="round";Y.fillStyle=U.scale("a",0.4).toString();var W=Math.min(O.first.x,O.second.x),V=Math.min(O.first.y,O.second.y),X=Math.abs(O.second.x-O.first.x),S=Math.abs(O.second.y-O.first.y);Y.fillRect(W,V,X,S);Y.strokeRect(W,V,X,S);Y.restore()}})}A.plot.plugins.push({init:B,options:{selection:{mode:null,color:"#e8cfac"}},name:"selection",version:"1.0"})})(jQuery);
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.stack.js
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
-Flot plugin for stacking data sets, i.e. putting them on top of each
-other, for accumulative graphs. Note that the plugin assumes the data
-is sorted on x. Also note that stacking a mix of positive and negative
-values in most instances doesn't make sense (so it looks weird).
-
-Two or more series are stacked when their "stack" attribute is set to
-the same key (which can be any number or string or just "true"). To
-specify the default stack, you can set
-
-  series: {
-    stack: null or true or key (number/string)
-  }
-
-or specify it for a specific series
-
-  $.plot($("#placeholder"), [{ data: [ ... ], stack: true ])
-  
-The stacking order is determined by the order of the data series in
-the array (later series end up on top of the previous).
-
-Internally, the plugin modifies the datapoints in each series, adding
-an offset to the y value. For line series, extra data points are
-inserted through interpolation. For bar charts, the second y value is
-also adjusted.
-*/
-
-(function ($) {
-    var options = {
-        series: { stack: null } // or number/string
-    };
-    
-    function init(plot) {
-        function findMatchingSeries(s, allseries) {
-            var res = null
-            for (var i = 0; i < allseries.length; ++i) {
-                if (s == allseries[i])
-                    break;
-                
-                if (allseries[i].stack == s.stack)
-                    res = allseries[i];
-            }
-            
-            return res;
-        }
-        
-        function stackData(plot, s, datapoints) {
-            if (s.stack == null)
-                return;
-
-            var other = findMatchingSeries(s, plot.getData());
-            if (!other)
-                return;
-            
-            var ps = datapoints.pointsize,
-                points = datapoints.points,
-                otherps = other.datapoints.pointsize,
-                otherpoints = other.datapoints.points,
-                newpoints = [],
-                px, py, intery, qx, qy, bottom,
-                withlines = s.lines.show, withbars = s.bars.show,
-                withsteps = withlines && s.lines.steps,
-                i = 0, j = 0, l;
-
-            while (true) {
-                if (i >= points.length)
-                    break;
-
-                l = newpoints.length;
-
-                if (j >= otherpoints.length
-                    || otherpoints[j] == null
-                    || points[i] == null) {
-                    // degenerate cases
-                    for (m = 0; m < ps; ++m)
-                        newpoints.push(points[i + m]);
-                    i += ps;
-                }
-                else {
-                    // cases where we actually got two points
-                    px = points[i];
-                    py = points[i + 1];
-                    qx = otherpoints[j];
-                    qy = otherpoints[j + 1];
-                    bottom = 0;
-
-                    if (px == qx) {
-                        for (m = 0; m < ps; ++m)
-                            newpoints.push(points[i + m]);
-
-                        newpoints[l + 1] += qy;
-                        bottom = qy;
-                        
-                        i += ps;
-                        j += otherps;
-                    }
-                    else if (px > qx) {
-                        // we got past point below, might need to
-                        // insert interpolated extra point
-                        if (withlines && i > 0 && points[i - ps] != null) {
-                            intery = py + (points[i - ps + 1] - py) * (qx - px) / (points[i - ps] - px);
-                            newpoints.push(qx);
-                            newpoints.push(intery + qy)
-                            for (m = 2; m < ps; ++m)
-                                newpoints.push(points[i + m]);
-                            bottom = qy; 
-                        }
-
-                        j += otherps;
-                    }
-                    else {
-                        for (m = 0; m < ps; ++m)
-                            newpoints.push(points[i + m]);
-                        
-                        // we might be able to interpolate a point below,
-                        // this can give us a better y
-                        if (withlines && j > 0 && otherpoints[j - ps] != null)
-                            bottom = qy + (otherpoints[j - ps + 1] - qy) * (px - qx) / (otherpoints[j - ps] - qx);
-
-                        newpoints[l + 1] += bottom;
-                        
-                        i += ps;
-                    }
-                    
-                    if (l != newpoints.length && withbars)
-                        newpoints[l + 2] += bottom;
-                }
-
-                // maintain the line steps invariant
-                if (withsteps && l != newpoints.length && l > 0
-                    && newpoints[l] != null
-                    && newpoints[l] != newpoints[l - ps]
-                    && newpoints[l + 1] != newpoints[l - ps + 1]) {
-                    for (m = 0; m < ps; ++m)
-                        newpoints[l + ps + m] = newpoints[l + m];
-                    newpoints[l + 1] = newpoints[l - ps + 1];
-                }
-            }
-            
-            datapoints.points = newpoints;
-        }
-        
-        plot.hooks.processDatapoints.push(stackData);
-    }
-    
-    $.plot.plugins.push({
-        init: init,
-        options: options,
-        name: 'stack',
-        version: '1.0'
-    });
-})(jQuery);
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.stack.min.js
+++ /dev/null
@@ -1,1 +0,0 @@
-(function(B){var A={series:{stack:null}};function C(F){function D(J,I){var H=null;for(var G=0;G<I.length;++G){if(J==I[G]){break}if(I[G].stack==J.stack){H=I[G]}}return H}function E(W,P,G){if(P.stack==null){return }var L=D(P,W.getData());if(!L){return }var T=G.pointsize,Y=G.points,H=L.datapoints.pointsize,S=L.datapoints.points,N=[],R,Q,I,a,Z,M,O=P.lines.show,K=P.bars.show,J=O&&P.lines.steps,X=0,V=0,U;while(true){if(X>=Y.length){break}U=N.length;if(V>=S.length||S[V]==null||Y[X]==null){for(m=0;m<T;++m){N.push(Y[X+m])}X+=T}else{R=Y[X];Q=Y[X+1];a=S[V];Z=S[V+1];M=0;if(R==a){for(m=0;m<T;++m){N.push(Y[X+m])}N[U+1]+=Z;M=Z;X+=T;V+=H}else{if(R>a){if(O&&X>0&&Y[X-T]!=null){I=Q+(Y[X-T+1]-Q)*(a-R)/(Y[X-T]-R);N.push(a);N.push(I+Z);for(m=2;m<T;++m){N.push(Y[X+m])}M=Z}V+=H}else{for(m=0;m<T;++m){N.push(Y[X+m])}if(O&&V>0&&S[V-T]!=null){M=Z+(S[V-T+1]-Z)*(R-a)/(S[V-T]-a)}N[U+1]+=M;X+=T}}if(U!=N.length&&K){N[U+2]+=M}}if(J&&U!=N.length&&U>0&&N[U]!=null&&N[U]!=N[U-T]&&N[U+1]!=N[U-T+1]){for(m=0;m<T;++m){N[U+T+m]=N[U+m]}N[U+1]=N[U-T+1]}}G.points=N}F.hooks.processDatapoints.push(E)}B.plot.plugins.push({init:C,options:A,name:"stack",version:"1.0"})})(jQuery);
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.threshold.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-Flot plugin for thresholding data. Controlled through the option
-"threshold" in either the global series options
-
-  series: {
-    threshold: {
-      below: number
-      color: colorspec
-    }
-  }
-
-or in a specific series
-
-  $.plot($("#placeholder"), [{ data: [ ... ], threshold: { ... }}])
-
-The data points below "below" are drawn with the specified color. This
-makes it easy to mark points below 0, e.g. for budget data.
-
-Internally, the plugin works by splitting the data into two series,
-above and below the threshold. The extra series below the threshold
-will have its label cleared and the special "originSeries" attribute
-set to the original series. You may need to check for this in hover
-events.
-*/
-
-(function ($) {
-    var options = {
-        series: { threshold: null } // or { below: number, color: color spec}
-    };
-    
-    function init(plot) {
-        function thresholdData(plot, s, datapoints) {
-            if (!s.threshold)
-                return;
-            
-            var ps = datapoints.pointsize, i, x, y, p, prevp,
-                thresholded = $.extend({}, s); // note: shallow copy
-
-            thresholded.datapoints = { points: [], pointsize: ps };
-            thresholded.label = null;
-            thresholded.color = s.threshold.color;
-            thresholded.threshold = null;
-            thresholded.originSeries = s;
-            thresholded.data = [];
-
-            var below = s.threshold.below,
-                origpoints = datapoints.points,
-                addCrossingPoints = s.lines.show;
-
-            threspoints = [];
-            newpoints = [];
-
-            for (i = 0; i < origpoints.length; i += ps) {
-                x = origpoints[i]
-                y = origpoints[i + 1];
-
-                prevp = p;
-                if (y < below)
-                    p = threspoints;
-                else
-                    p = newpoints;
-
-                if (addCrossingPoints && prevp != p && x != null
-                    && i > 0 && origpoints[i - ps] != null) {
-                    var interx = (x - origpoints[i - ps]) / (y - origpoints[i - ps + 1]) * (below - y) + x;
-                    prevp.push(interx);
-                    prevp.push(below);
-                    for (m = 2; m < ps; ++m)
-                        prevp.push(origpoints[i + m]);
-                    
-                    p.push(null); // start new segment
-                    p.push(null);
-                    for (m = 2; m < ps; ++m)
-                        p.push(origpoints[i + m]);
-                    p.push(interx);
-                    p.push(below);
-                    for (m = 2; m < ps; ++m)
-                        p.push(origpoints[i + m]);
-                }
-
-                p.push(x);
-                p.push(y);
-            }
-
-            datapoints.points = newpoints;
-            thresholded.datapoints.points = threspoints;
-            
-            if (thresholded.datapoints.points.length > 0)
-                plot.getData().push(thresholded);
-                
-            // FIXME: there are probably some edge cases left in bars
-        }
-        
-        plot.hooks.processDatapoints.push(thresholdData);
-    }
-    
-    $.plot.plugins.push({
-        init: init,
-        options: options,
-        name: 'threshold',
-        version: '1.0'
-    });
-})(jQuery);
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.flot.threshold.min.js
+++ /dev/null
@@ -1,1 +0,0 @@
-(function(B){var A={series:{threshold:null}};function C(D){function E(L,S,M){if(!S.threshold){return }var F=M.pointsize,I,O,N,G,K,H=B.extend({},S);H.datapoints={points:[],pointsize:F};H.label=null;H.color=S.threshold.color;H.threshold=null;H.originSeries=S;H.data=[];var P=S.threshold.below,Q=M.points,R=S.lines.show;threspoints=[];newpoints=[];for(I=0;I<Q.length;I+=F){O=Q[I];N=Q[I+1];K=G;if(N<P){G=threspoints}else{G=newpoints}if(R&&K!=G&&O!=null&&I>0&&Q[I-F]!=null){var J=(O-Q[I-F])/(N-Q[I-F+1])*(P-N)+O;K.push(J);K.push(P);for(m=2;m<F;++m){K.push(Q[I+m])}G.push(null);G.push(null);for(m=2;m<F;++m){G.push(Q[I+m])}G.push(J);G.push(P);for(m=2;m<F;++m){G.push(Q[I+m])}}G.push(O);G.push(N)}M.points=newpoints;H.datapoints.points=threspoints;if(H.datapoints.points.length>0){L.getData().push(H)}}D.hooks.processDatapoints.push(E)}B.plot.plugins.push({init:C,options:A,name:"threshold",version:"1.0"})})(jQuery);
\ No newline at end of file
deleted file mode 100644
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/content/flot/jquery.js
+++ /dev/null
@@ -1,4376 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.3.2
- * http://jquery.com/
- *
- * Copyright (c) 2009 John Resig
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
- *
- * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
- * Revision: 6246
- */
-(function(){
-
-var 
-	// Will speed up references to window, and allows munging its name.
-	window = this,
-	// Will speed up references to undefined, and allows munging its name.
-	undefined,
-	// Map over jQuery in case of overwrite
-	_jQuery = window.jQuery,
-	// Map over the $ in case of overwrite
-	_$ = window.$,
-
-	jQuery = window.jQuery = window.$ = function( selector, context ) {
-		// The jQuery object is actually just the init constructor 'enhanced'
-		return new jQuery.fn.init( selector, context );
-	},
-
-	// A simple way to check for HTML strings or ID strings
-	// (both of which we optimize for)
-	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
-	// Is it a simple selector
-	isSimple = /^.[^:#\[\.,]*$/;
-
-jQuery.fn = jQuery.prototype = {
-	init: function( selector, context ) {
-		// Make sure that a selection was provided
-		selector = selector || document;
-
-		// Handle $(DOMElement)
-		if ( selector.nodeType ) {
-			this[0] = selector;
-			this.length = 1;
-			this.context = selector;
-			return this;
-		}
-		// Handle HTML strings
-		if ( typeof selector === "string" ) {
-			// Are we dealing with HTML string or an ID?
-			var match = quickExpr.exec( selector );
-
-			// Verify a match, and that no context was specified for #id
-			if ( match && (match[1] || !context) ) {
-
-				// HANDLE: $(html) -> $(array)
-				if ( match[1] )
-					selector = jQuery.clean( [ match[1] ], context );
-
-				// HANDLE: $("#id")
-				else {
-					var elem = document.getElementById( match[3] );
-
-					// Handle the case where IE and Opera return items
-					// by name instead of ID
-					if ( elem && elem.id != match[3] )
-						return jQuery().find( selector );
-
-					// Otherwise, we inject the element directly into the jQuery object
-					var ret = jQuery( elem || [] );
-					ret.context = document;
-					ret.selector = selector;
-					return ret;
-				}
-
-			// HANDLE: $(expr, [context])
-			// (which is just equivalent to: $(content).find(expr)
-			} else
-				return jQuery( context ).find( selector );
-
-		// HANDLE: $(function)
-		// Shortcut for document ready
-		} else if ( jQuery.isFunction( selector ) )
-			return jQuery( document ).ready( selector );
-
-		// Make sure that old selector state is passed along
-		if ( selector.selector && selector.context ) {
-			this.selector = selector.selector;
-			this.context = selector.context;
-		}
-
-		return this.setArray(jQuery.isArray( selector ) ?
-			selector :
-			jQuery.makeArray(selector));
-	},
-
-	// Start with an empty selector
-	selector: "",
-
-	// The current version of jQuery being used
-	jquery: "1.3.2",
-
-	// The number of elements contained in the matched element set
-	size: function() {
-		return this.length;
-	},
-
-	// Get the Nth element in the matched element set OR
-	// Get the whole matched element set as a clean array
-	get: function( num ) {
-		return num === undefined ?
-
-			// Return a 'clean' array
-			Array.prototype.slice.call( this ) :
-
-			// Return just the object
-			this[ num ];
-	},
-
-	// Take an array of elements and push it onto the stack
-	// (returning the new matched element set)
-	pushStack: function( elems, name, selector ) {
-		// Build a new jQuery matched element set
-		var ret = jQuery( elems );
-
-		// Add the old object onto the stack (as a reference)
-		ret.prevObject = this;
-
-		ret.context = this.context;
-
-		if ( name === "find" )
-			ret.selector = this.selector + (this.selector ? " " : "") + selector;
-		else if ( name )
-			ret.selector = this.selector + "." + name + "(" + selector + ")";
-
-		// Return the newly-formed element set
-		return ret;
-	},
-
-	// Force the current matched set of elements to become
-	// the specified array of elements (destroying the stack in the process)
-	// You should use pushStack() in order to do this, but maintain the stack
-	setArray: function( elems ) {
-		// Resetting the length to 0, then using the native Array push
-		// is a super-fast way to populate an object with array-like properties
-		this.length = 0;
-		Array.prototype.push.apply( this, elems );
-
-		return this;
-	},
-
-	// Execute a callback for every element in the matched set.
-	// (You can seed the arguments with an array of args, but this is
-	// only used internally.)
-	each: function( callback, args ) {
-		return jQuery.each( this, callback, args );
-	},
-
-	// Determine the position of an element within
-	// the matched set of elements
-	index: function( elem ) {
-		// Locate the position of the desired element
-		return jQuery.inArray(
-			// If it receives a jQuery object, the first element is used
-			elem && elem.jquery ? elem[0] : elem
-		, this );
-	},
-
-	attr: function( name, value, type ) {
-		var options = name;
-
-		// Look for the case where we're accessing a style value
-		if ( typeof name === "string" )
-			if ( value === undefined )
-				return this[0] && jQuery[ type || "attr" ]( this[0], name );
-
-			else {
-				options = {};
-				options[ name ] = value;
-			}
-
-		// Check to see if we're setting style values
-		return this.each(function(i){
-			// Set all the styles
-			for ( name in options )
-				jQuery.attr(
-					type ?
-						this.style :
-						this,
-					name, jQuery.prop( this, options[ name ], type, i, name )
-				);
-		});
-	},
-
-	css: function( key, value ) {
-		// ignore negative width and height values
-		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
-			value = undefined;
-		return this.attr( key, value, "curCSS" );
-	},
-
-	text: function( text ) {
-		if ( typeof text !== "object" && text != null )
-			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
-
-		var ret = "";
-
-		jQuery.each( text || this, function(){
-			jQuery.each( this.childNodes, function(){
-				if ( this.nodeType != 8 )
-					ret += this.nodeType != 1 ?
-						this.nodeValue :
-						jQuery.fn.text( [ this ] );
-			});
-		});
-
-		return ret;
-	},
-
-	wrapAll: function( html ) {
-		if ( this[0] ) {
-			// The elements to wrap the target around
-			var wrap = jQuery( html, this[0].ownerDocument ).clone();
-
-			if ( this[0].parentNode )
-				wrap.insertBefore( this[0] );
-
-			wrap.map(function(){
-				var elem = this;
-
-				while ( elem.firstChild )
-					elem = elem.firstChild;
-
-				return elem;
-			}).append(this);
-		}
-
-		return this;
-	},
-
-	wrapInner: function( html ) {
-		return this.each(function(){
-			jQuery( this ).contents().wrapAll( html );
-		});
-	},
-
-	wrap: function( html ) {
-		return this.each(function(){
-			jQuery( this ).wrapAll( html );
-		});
-	},
-
-	append: function() {
-		return this.domManip(arguments, true, function(elem){
-			if (this.nodeType == 1)
-				this.appendChild( elem );
-		});
-	},
-
-	prepend: function() {
-		return this.domManip(arguments, true, function(elem){
-			if (this.nodeType == 1)
-				this.insertBefore( elem, this.firstChild );
-		});
-	},
-
-	before: function() {
-		return this.domManip(arguments, false, function(elem){
-			this.parentNode.insertBefore( elem, this );
-		});
-	},
-
-	after: function() {
-		return this.domManip(arguments, false, function(elem){
-			this.parentNode.insertBefore( elem, this.nextSibling );
-		});
-	},
-
-	end: function() {
-		return this.prevObject || jQuery( [] );
-	},
-
-	// For internal use only.
-	// Behaves like an Array's method, not like a jQuery method.
-	push: [].push,
-	sort: [].sort,
-	splice: [].splice,
-
-	find: function( selector ) {
-		if ( this.length === 1 ) {
-			var ret = this.pushStack( [], "find", selector );
-			ret.length = 0;
-			jQuery.find( selector, this[0], ret );
-			return ret;
-		} else {
-			return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
-				return jQuery.find( selector, elem );
-			})), "find", selector );
-		}
-	},
-
-	clone: function( events ) {
-		// Do the clone
-		var ret = this.map(function(){
-			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
-				// IE copies events bound via attachEvent when
-				// using cloneNode. Calling detachEvent on the
-				// clone will also remove the events from the orignal
-				// In order to get around this, we use innerHTML.
-				// Unfortunately, this means some modifications to
-				// attributes in IE that are actually only stored
-				// as properties will not be copied (such as the
-				// the name attribute on an input).
-				var html = this.outerHTML;
-				if ( !html ) {
-					var div = this.ownerDocument.createElement("div");
-					div.appendChild( this.cloneNode(true) );
-					html = div.innerHTML;
-				}
-
-				return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
-			} else
-				return this.cloneNode(true);
-		});
-
-		// Copy the events from the original to the clone
-		if ( events === true ) {
-			var orig = this.find("*").andSelf(), i = 0;
-
-			ret.find("*").andSelf().each(function(){
-				if ( this.nodeName !== orig[i].nodeName )
-					return;
-
-				var events = jQuery.data( orig[i], "events" );
-
-				for ( var type in events ) {
-					for ( var handler in events[ type ] ) {
-						jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
-					}
-				}
-
-				i++;
-			});
-		}
-
-		// Return the cloned set
-		return ret;
-	},
-
-	filter: function( selector ) {
-		return this.pushStack(
-			jQuery.isFunction( selector ) &&
-			jQuery.grep(this, function(elem, i){
-				return selector.call( elem, i );
-			}) ||
-
-			jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
-				return elem.nodeType === 1;
-			}) ), "filter", selector );
-	},
-
-	closest: function( selector ) {
-		var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
-			closer = 0;
-
-		return this.map(function(){
-			var cur = this;
-			while ( cur && cur.ownerDocument ) {
-				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
-					jQuery.data(cur, "closest", closer);
-					return cur;
-				}
-				cur = cur.parentNode;
-				closer++;
-			}
-		});
-	},
-
-	not: function( selector ) {
-		if ( typeof selector === "string" )
-			// test special case where just one selector is passed in
-			if ( isSimple.test( selector ) )
-				return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
-			else
-				selector = jQuery.multiFilter( selector, this );
-
-		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
-		return this.filter(function() {
-			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
-		});
-	},
-
-	add: function( selector ) {
-		return this.pushStack( jQuery.unique( jQuery.merge(
-			this.get(),
-			typeof selector === "string" ?
-				jQuery( selector ) :
-				jQuery.makeArray( selector )
-		)));
-	},
-
-	is: function( selector ) {
-		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
-	},
-
-	hasClass: function( selector ) {
-		return !!selector && this.is( "." + selector );
-	},
-
-	val: function( value ) {
-		if ( value === undefined ) {			
-			var elem = this[0];
-
-			if ( elem ) {
-				if( jQuery.nodeName( elem, 'option' ) )
-					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
-				
-				// We need to handle select boxes special
-				if ( jQuery.nodeName( elem, "select" ) ) {
-					var index = elem.selectedIndex,
-						values = [],
-						options = elem.options,
-						one = elem.type == "select-one";
-
-					// Nothing was selected
-					if ( index < 0 )
-						return null;
-
-					// Loop through all the selected options
-					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
-						var option = options[ i ];
-
-						if ( option.selected ) {
-							// Get the specifc value for the option
-							value = jQuery(option).val();
-
-							// We don't need an array for one selects
-							if ( one )
-								return value;
-
-							// Multi-Selects return an array
-							values.push( value );
-						}
-					}
-
-					return values;				
-				}
-
-				// Everything else, we just grab the value
-				return (elem.value || "").replace(/\r/g, "");
-
-			}
-
-			return undefined;
-		}
-
-		if ( typeof value === "number" )
-			value += '';
-
-		return this.each(function(){
-			if ( this.nodeType != 1 )
-				return;
-
-			if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
-				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
-					jQuery.inArray(this.name, value) >= 0);
-
-			else if ( jQuery.nodeName( this, "select" ) ) {
-				var values = jQuery.makeArray(value);
-
-				jQuery( "option", this ).each(function(){
-					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
-						jQuery.inArray( this.text, values ) >= 0);
-				});
-
-				if ( !values.length )
-					this.selectedIndex = -1;
-
-			} else
-				this.value = value;
-		});
-	},
-
-	html: function( value ) {
-		return value === undefined ?
-			(this[0] ?
-				this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
-				null) :
-			this.empty().append( value );
-	},
-
-	replaceWith: function( value ) {
-		return this.after( value ).remove();
-	},
-
-	eq: function( i ) {
-		return this.slice( i, +i + 1 );
-	},
-
-	slice: function() {
-		return this.pushStack( Array.prototype.slice.apply( this, arguments ),
-			"slice", Array.prototype.slice.call(arguments).join(",") );
-	},
-
-	map: function( callback ) {
-		return this.pushStack( jQuery.map(this, function(elem, i){
-			return callback.call( elem, i, elem );
-		}));
-	},
-
-	andSelf: function() {
-		return this.add( this.prevObject );
-	},
-
-	domManip: function( args, table, callback ) {
-		if ( this[0] ) {
-			var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
-				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
-				first = fragment.firstChild;
-
-			if ( first )
-				for ( var i = 0, l = this.length; i < l; i++ )
-					callback.call( root(this[i], first), this.length > 1 || i > 0 ?
-							fragment.cloneNode(true) : fragment );
-		
-			if ( scripts )
-				jQuery.each( scripts, evalScript );
-		}
-
-		return this;
-		
-		function root( elem, cur ) {
-			return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
-				(elem.getElementsByTagName("tbody")[0] ||
-				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
-				elem;
-		}
-	}
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
-function evalScript( i, elem ) {
-	if ( elem.src )
-		jQuery.ajax({
-			url: elem.src,
-			async: false,
-			dataType: "script"
-		});
-
-	else
-		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
-
-	if ( elem.parentNode )
-		elem.parentNode.removeChild( elem );
-}
-
-function now(){
-	return +new Date;
-}
-
-jQuery.extend = jQuery.fn.extend = function() {
-	// copy reference to target object
-	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
-
-	// Handle a deep copy situation
-	if ( typeof target === "boolean" ) {
-		deep = target;
-		target = arguments[1] || {};
-		// skip the boolean and the target
-		i = 2;
-	}
-
-	// Handle case when target is a string or something (possible in deep copy)
-	if ( typeof target !== "object" && !jQuery.isFunction(target) )
-		target = {};
-
-	// extend jQuery itself if only one argument is passed
-	if ( length == i ) {
-		target = this;
-		--i;
-	}
-
-	for ( ; i < length; i++ )
-		// Only deal with non-null/undefined values
-		if ( (options = arguments[ i ]) != null )
-			// Extend the base object
-			for ( var name in options ) {
-				var src = target[ name ], copy = options[ name ];
-
-				// Prevent never-ending loop
-				if ( target === copy )
-					continue;
-
-				// Recurse if we're merging object values
-				if ( deep && copy && typeof copy === "object" && !copy.nodeType )
-					target[ name ] = jQuery.extend( deep, 
-						// Never move original objects, clone them
-						src || ( copy.length != null ? [ ] : { } )
-					, copy );
-
-				// Don't bring in undefined values
-				else if ( copy !== undefined )
-					target[ name ] = copy;
-
-			}
-
-	// Return the modified object
-	return target;
-};
-
-// exclude the following css properties to add px
-var	exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
-	// cache defaultView
-	defaultView = document.defaultView || {},
-	toString = Object.prototype.toString;
-
-jQuery.extend({
-	noConflict: function( deep ) {
-		window.$ = _$;
-
-		if ( deep )
-			window.jQuery = _jQuery;
-
-		return jQuery;
-	},
-
-	// See test/unit/core.js for details concerning isFunction.
-	// Since version 1.3, DOM methods and functions like alert
-	// aren't supported. They return false on IE (#2968).
-	isFunction: function( obj ) {
-		return toString.call(obj) === "[object Function]";
-	},
-
-	isArray: function( obj ) {
-		return toString.call(obj) === "[object Array]";
-	},
-
-	// check if an element is in a (or is an) XML document
-	isXMLDoc: function( elem ) {
-		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
-			!!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
-	},
-
-	// Evalulates a script in a global context
-	globalEval: function( data ) {
-		if ( data && /\S/.test(data) ) {
-			// Inspired by code by Andrea Giammarchi
-			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
-			var head = document.getElementsByTagName("head")[0] || document.documentElement,
-				script = document.createElement("script");
-
-			script.type = "text/javascript";
-			if ( jQuery.support.scriptEval )
-				script.appendChild( document.createTextNode( data ) );
-			else
-				script.text = data;
-
-			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
-			// This arises when a base node is used (#2709).
-			head.insertBefore( script, head.firstChild );
-			head.removeChild( script );
-		}
-	},
-
-	nodeName: function( elem, name ) {
-		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
-	},
-
-	// args is for internal usage only
-	each: function( object, callback, args ) {
-		var name, i = 0, length = object.length;
-
-		if ( args ) {
-			if ( length === undefined ) {
-				for ( name in object )
-					if ( callback.apply( object[ name ], args ) === false )
-						break;
-			} else
-				for ( ; i < length; )
-					if ( callback.apply( object[ i++ ], args ) === false )
-						break;
-
-		// A special, fast, case for the most common use of each
-		} else {
-			if ( length === undefined ) {
-				for ( name in object )
-					if ( callback.call( object[ name ], name, object[ name ] ) === false )
-						break;
-			} else
-				for ( var value = object[0];
-					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
-		}
-
-		return object;
-	},
-
-	prop: function( elem, value, type, i, name ) {
-		// Handle executable functions
-		if ( jQuery.isFunction( value ) )
-			value = value.call( elem, i );
-
-		// Handle passing in a number to a CSS property
-		return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
-			value + "px" :
-			value;
-	},
-
-	className: {
-		// internal only, use addClass("class")
-		add: function( elem, classNames ) {
-			jQuery.each((classNames || "").split(/\s+/), function(i, className){
-				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
-					elem.className += (elem.className ? " " : "") + className;
-			});
-		},
-
-		// internal only, use removeClass("class")
-		remove: function( elem, classNames ) {
-			if (elem.nodeType == 1)
-				elem.className = classNames !== undefined ?
-					jQuery.grep(elem.className.split(/\s+/), function(className){
-						return !jQuery.className.has( classNames, className );
-					}).join(" ") :
-					"";
-		},
-
-		// internal only, use hasClass("class")
-		has: function( elem, className ) {
-			return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
-		}
-	},
-
-	// A method for quickly swapping in/out CSS properties to get correct calculations
-	swap: function( elem, options, callback ) {
-		var old = {};
-		// Remember the old values, and insert the new ones
-		for ( var name in options ) {
-			old[ name ] = elem.style[ name ];
-			elem.style[ name ] = options[ name ];
-		}
-
-		callback.call( elem );
-
-		// Revert the old values
-		for ( var name in options )
-			elem.style[ name ] = old[ name ];
-	},
-
-	css: function( elem, name, force, extra ) {
-		if ( name == "width" || name == "height" ) {
-			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
-
-			function getWH() {
-				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
-
-				if ( extra === "border" )
-					return;
-
-				jQuery.each( which, function() {
-					if ( !extra )
-						val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
-					if ( extra === "margin" )
-						val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
-					else
-						val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
-				});
-			}
-
-			if ( elem.offsetWidth !== 0 )
-				getWH();
-			else
-				jQuery.swap( elem, props, getWH );
-
-			return Math.max(0, Math.round(val));
-		}
-
-		return jQuery.curCSS( elem, name, force );
-	},
-
-	curCSS: function( elem, name, force ) {
-		var ret, style = elem.style;
-
-		// We need to handle opacity special in IE
-		if ( name == "opacity" && !jQuery.support.opacity ) {
-			ret = jQuery.attr( style, "opacity" );
-
-			return ret == "" ?
-				"1" :
-				ret;
-		}
-
-		// Make sure we're using the right name for getting the float value
-		if ( name.match( /float/i ) )
-			name = styleFloat;
-
-		if ( !force && style && style[ name ] )
-			ret = style[ name ];
-
-		else if ( defaultView.getComputedStyle ) {
-
-			// Only "float" is needed here
-			if ( name.match( /float/i ) )
-				name = "float";
-
-			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
-
-			var computedStyle = defaultView.getComputedStyle( elem, null );
-
-			if ( computedStyle )
-				ret = computedStyle.getPropertyValue( name );
-
-			// We should always get a number back from opacity
-			if ( name == "opacity" && ret == "" )
-				ret = "1";
-
-		} else if ( elem.currentStyle ) {
-			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
-				return letter.toUpperCase();
-			});
-
-			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
-
-			// From the awesome hack by Dean Edwards
-			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
-
-			// If we're not dealing with a regular pixel number
-			// but a number that has a weird ending, we need to convert it to pixels
-			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
-				// Remember the original values
-				var left = style.left, rsLeft = elem.runtimeStyle.left;
-
-				// Put in the new values to get a computed value out
-				elem.runtimeStyle.left = elem.currentStyle.left;
-				style.left = ret || 0;
-				ret = style.pixelLeft + "px";
-
-				// Revert the changed values
-				style.left = left;
-				elem.runtimeStyle.left = rsLeft;
-			}
-		}
-
-		return ret;
-	},
-
-	clean: function( elems, context, fragment ) {
-		context = context || document;
-
-		// !context.createElement fails in IE with an error but returns typeof 'object'
-		if ( typeof context.createElement === "undefined" )
-			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
-
-		// If a single string is passed in and it's a single tag
-		// just do a createElement and skip the rest
-		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
-			var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
-			if ( match )
-				return [ context.createElement( match[1] ) ];
-		}
-
-		var ret = [], scripts = [], div = context.createElement("div");
-
-		jQuery.each(elems, function(i, elem){
-			if ( typeof elem === "number" )
-				elem += '';
-
-			if ( !elem )
-				return;
-
-			// Convert html string into DOM nodes
-			if ( typeof elem === "string" ) {
-				// Fix "XHTML"-style tags in all browsers
-				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
-					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
-						all :
-						front + "></" + tag + ">";
-				});
-
-				// Trim whitespace, otherwise indexOf won't work as expected
-				var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
-
-				var wrap =
-					// option or optgroup
-					!tags.indexOf("<opt") &&
-					[ 1, "<select multiple='multiple'>", "</select>" ] ||
-
-					!tags.indexOf("<leg") &&
-					[ 1, "<fieldset>", "</fieldset>" ] ||
-
-					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
-					[ 1, "<table>", "</table>" ] ||
-
-					!tags.indexOf("<tr") &&
-					[ 2, "<table><tbody>", "</tbody></table>" ] ||
-
-				 	// <thead> matched above
-					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
-					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
-
-					!tags.indexOf("<col") &&
-					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
-
-					// IE can't serialize <link> and <script> tags normally
-					!jQuery.support.htmlSerialize &&
-					[ 1, "div<div>", "</div>" ] ||
-
-					[ 0, "", "" ];
-
-				// Go to html and back, then peel off extra wrappers
-				div.innerHTML = wrap[1] + elem + wrap[2];
-
-				// Move to the right depth
-				while ( wrap[0]-- )
-					div = div.lastChild;
-
-				// Remove IE's autoinserted <tbody> from table fragments
-				if ( !jQuery.support.tbody ) {
-
-					// String was a <table>, *may* have spurious <tbody>
-					var hasBody = /<tbody/i.test(elem),
-						tbody = !tags.indexOf("<table") && !hasBody ?
-							div.firstChild && div.firstChild.childNodes :
-
-						// String was a bare <thead> or <tfoot>
-						wrap[1] == "<table>" && !hasBody ?
-							div.childNodes :
-							[];
-
-					for ( var j = tbody.length - 1; j >= 0 ; --j )
-						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
-							tbody[ j ].parentNode.removeChild( tbody[ j ] );
-
-					}
-
-				// IE completely kills leading whitespace when innerHTML is used
-				if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
-					div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
-				
-				elem = jQuery.makeArray( div.childNodes );
-			}
-
-			if ( elem.nodeType )
-				ret.push( elem );
-			else
-				ret = jQuery.merge( ret, elem );
-
-		});
-
-		if ( fragment ) {
-			for ( var i = 0; ret[i]; i++ ) {
-				if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
-					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
-				} else {
-					if ( ret[i].nodeType === 1 )
-						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
-					fragment.appendChild( ret[i] );
-				}
-			}
-			
-			return scripts;
-		}
-
-		return ret;
-	},
-
-	attr: function( elem, name, value ) {
-		// don't set attributes on text and comment nodes
-		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
-			return undefined;
-
-		var notxml = !jQuery.isXMLDoc( elem ),
-			// Whether we are setting (or getting)
-			set = value !== undefined;
-
-		// Try to normalize/fix the name
-		name = notxml && jQuery.props[ name ] || name;
-
-		// Only do all the following if this is a node (faster for style)
-		// IE elem.getAttribute passes even for style
-		if ( elem.tagName ) {
-
-			// These attributes require special treatment
-			var special = /href|src|style/.test( name );
-
-			// Safari mis-reports the default selected property of a hidden option
-			// Accessing the parent's selectedIndex property fixes it
-			if ( name == "selected" && elem.parentNode )
-				elem.parentNode.selectedIndex;
-
-			// If applicable, access the attribute via the DOM 0 way
-			if ( name in elem && notxml && !special ) {
-				if ( set ){
-					// We can't allow the type property to be changed (since it causes problems in IE)
-					if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
-						throw "type property can't be changed";
-
-					elem[ name ] = value;
-				}
-
-				// browsers index elements by id/name on forms, give priority to attributes.
-				if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
-					return elem.getAttributeNode( name ).nodeValue;
-
-				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
-				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
-				if ( name == "tabIndex" ) {
-					var attributeNode = elem.getAttributeNode( "tabIndex" );
-					return attributeNode && attributeNode.specified
-						? attributeNode.value
-						: elem.nodeName.match(/(button|input|object|select|textarea)/i)
-							? 0
-							: elem.nodeName.match(/^(a|area)$/i) && elem.href
-								? 0
-								: undefined;
-				}
-
-				return elem[ name ];
-			}
-
-			if ( !jQuery.support.style && notxml &&  name == "style" )
-				return jQuery.attr( elem.style, "cssText", value );
-
-			if ( set )
-				// convert the value to a string (all browsers do this but IE) see #1070
-				elem.setAttribute( name, "" + value );
-
-			var attr = !jQuery.support.hrefNormalized && notxml && special
-					// Some attributes require a special call on IE
-					? elem.getAttribute( name, 2 )
-					: elem.getAttribute( name );
-
-			// Non-existent attributes return null, we normalize to undefined
-			return attr === null ? undefined : attr;
-		}
-
-		// elem is actually elem.style ... set the style
-
-		// IE uses filters for opacity
-		if ( !jQuery.support.opacity && name == "opacity" ) {
-			if ( set ) {
-				// IE has trouble with opacity if it does not have layout
-				// Force it by setting the zoom level
-				elem.zoom = 1;
-
-				// Set the alpha filter to set the opacity
-				elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
-					(parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
-			}
-
-			return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
-				(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
-				"";
-		}
-
-		name = name.replace(/-([a-z])/ig, function(all, letter){
-			return letter.toUpperCase();
-		});
-
-		if ( set )
-			elem[ name ] = value;
-
-		return elem[ name ];
-	},
-
-	trim: function( text ) {
-		return (text || "").replace( /^\s+|\s+$/g, "" );
-	},
-
-	makeArray: function( array ) {
-		var ret = [];
-
-		if( array != null ){
-			var i = array.length;
-			// The window, strings (and functions) also have 'length'
-			if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
-				ret[0] = array;
-			else
-				while( i )
-					ret[--i] = array[i];
-		}
-
-		return ret;
-	},
-
-	inArray: function( elem, array ) {
-		for ( var i = 0, length = array.length; i < length; i++ )
-		// Use === because on IE, window == document
-			if ( array[ i ] === elem )
-				return i;
-
-		return -1;
-	},
-
-	merge: function( first, second ) {
-		// We have to loop this way because IE & Opera overwrite the length
-		// expando of getElementsByTagName
-		var i = 0, elem, pos = first.length;
-		// Also, we need to make sure that the correct elements are being returned
-		// (IE returns comment nodes in a '*' query)
-		if ( !jQuery.support.getAll ) {
-			while ( (elem = second[ i++ ]) != null )
-				if ( elem.nodeType != 8 )
-					first[ pos++ ] = elem;
-
-		} else
-			while ( (elem = second[ i++ ]) != null )
-				first[ pos++ ] = elem;
-
-		return first;
-	},
-
-	unique: function( array ) {
-		var ret = [], done = {};
-
-		try {
-
-			for ( var i = 0, length = array.length; i < length; i++ ) {
-				var id = jQuery.data( array[ i ] );
-
-				if ( !done[ id ] ) {
-					done[ id ] = true;
-					ret.push( array[ i ] );
-				}
-			}
-
-		} catch( e ) {
-			ret = array;
-		}
-
-		return ret;
-	},
-
-	grep: function( elems, callback, inv ) {
-		var ret = [];
-
-		// Go through the array, only saving the items
-		// that pass the validator function
-		for ( var i = 0, length = elems.length; i < length; i++ )
-			if ( !inv != !callback( elems[ i ], i ) )
-				ret.push( elems[ i ] );
-
-		return ret;
-	},
-
-	map: function( elems, callback ) {
-		var ret = [];
-
-		// Go through the array, translating each of the items to their
-		// new value (or values).
-		for ( var i = 0, length = elems.length; i < length; i++ ) {
-			var value = callback( elems[ i ], i );
-
-			if ( value != null )
-				ret[ ret.length ] = value;
-		}
-
-		return ret.concat.apply( [], ret );
-	}
-});
-
-// Use of jQuery.browser is deprecated.
-// It's included for backwards compatibility and plugins,
-// although they should work to migrate away.
-
-var userAgent = navigator.userAgent.toLowerCase();
-
-// Figure out what browser is being used
-jQuery.browser = {
-	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
-	safari: /webkit/.test( userAgent ),
-	opera: /opera/.test( userAgent ),
-	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
-	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
-};
-
-jQuery.each({
-	parent: function(elem){return elem.parentNode;},
-	parents: function(elem){return jQuery.dir(elem,"parentNode");},
-	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
-	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
-	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
-	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
-	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
-	children: function(elem){return jQuery.sibling(elem.firstChild);},
-	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
-}, function(name, fn){
-	jQuery.fn[ name ] = function( selector ) {
-		var ret = jQuery.map( this, fn );
-
-		if ( selector && typeof selector == "string" )
-			ret = jQuery.multiFilter( selector, ret );
-
-		return this.pushStack( jQuery.unique( ret ), name, selector );
-	};
-});
-
-jQuery.each({
-	appendTo: "append",
-	prependTo: "prepend",
-	insertBefore: "before",
-	insertAfter: "after",
-	replaceAll: "replaceWith"
-}, function(name, original){
-	jQuery.fn[ name ] = function( selector ) {
-		var ret = [], insert = jQuery( selector );
-
-		for ( var i = 0, l = insert.length; i < l; i++ ) {
-			var elems = (i > 0 ? this.clone(true) : this).get();
-			jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
-			ret = ret.concat( elems );
-		}
-
-		return this.pushStack( ret, name, selector );
-	};
-});
-
-jQuery.each({
-	removeAttr: function( name ) {
-		jQuery.attr( this, name, "" );
-		if (this.nodeType == 1)
-			this.removeAttribute( name );
-	},
-
-	addClass: function( classNames ) {
-		jQuery.className.add( this, classNames );
-	},
-
-	removeClass: function( classNames ) {
-		jQuery.className.remove( this, classNames );
-	},
-
-	toggleClass: function( classNames, state ) {
-		if( typeof state !== "boolean" )
-			state = !jQuery.className.has( this, classNames );
-		jQuery.className[ state ? "add" : "remove" ]( this, classNames );
-	},
-
-	remove: function( selector ) {
-		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
-			// Prevent memory leaks
-			jQuery( "*", this ).add([this]).each(function(){
-				jQuery.event.remove(this);
-				jQuery.removeData(this);
-			});
-			if (this.parentNode)
-				this.parentNode.removeChild( this );
-		}
-	},
-
-	empty: function() {
-		// Remove element nodes and prevent memory leaks
-		jQuery(this).children().remove();
-
-		// Remove any remaining nodes
-		while ( this.firstChild )
-			this.removeChild( this.firstChild );
-	}
-}, function(name, fn){
-	jQuery.fn[ name ] = function(){
-		return this.each( fn, arguments );
-	};
-});
-
-// Helper function used by the dimensions and offset modules
-function num(elem, prop) {
-	return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
-}
-var expando = "jQuery" + now(), uuid = 0, windowData = {};
-
-jQuery.extend({
-	cache: {},
-
-	data: function( elem, name, data ) {
-		elem = elem == window ?
-			windowData :
-			elem;
-
-		var id = elem[ expando ];
-
-		// Compute a unique ID for the element
-		if ( !id )
-			id = elem[ expando ] = ++uuid;
-
-		// Only generate the data cache if we're
-		// trying to access or manipulate it
-		if ( name && !jQuery.cache[ id ] )
-			jQuery.cache[ id ] = {};
-
-		// Prevent overriding the named cache with undefined values
-		if ( data !== undefined )
-			jQuery.cache[ id ][ name ] = data;
-
-		// Return the named cache data, or the ID for the element
-		return name ?
-			jQuery.cache[ id ][ name ] :
-			id;
-	},
-
-	removeData: function( elem, name ) {
-		elem = elem == window ?
-			windowData :
-			elem;
-
-		var id = elem[ expando ];
-
-		// If we want to remove a specific section of the element's data
-		if ( name ) {
-			if ( jQuery.cache[ id ] ) {
-				// Remove the section of cache data
-				delete jQuery.cache[ id ][ name ];
-
-				// If we've removed all the data, remove the element's cache
-				name = "";
-
-				for ( name in jQuery.cache[ id ] )
-					break;
-
-				if ( !name )
-					jQuery.removeData( elem );
-			}
-
-		// Otherwise, we want to remove all of the element's data
-		} else {
-			// Clean up the element expando
-			try {
-				delete elem[ expando ];
-			} catch(e){
-				// IE has trouble directly removing the expando
-				// but it's ok with using removeAttribute
-				if ( elem.removeAttribute )
-					elem.removeAttribute( expando );
-			}
-
-			// Completely remove the data cache
-			delete jQuery.cache[ id ];
-		}
-	},
-	queue: function( elem, type, data ) {
-		if ( elem ){
-	
-			type = (type || "fx") + "queue";
-	
-			var q = jQuery.data( elem, type );
-	
-			if ( !q || jQuery.isArray(data) )
-				q = jQuery.data( elem, type, jQuery.makeArray(data) );
-			else if( data )
-				q.push( data );
-	
-		}
-		return q;
-	},
-
-	dequeue: function( elem, type ){
-		var queue = jQuery.queue( elem, type ),
-			fn = queue.shift();
-		
-		if( !type || type === "fx" )
-			fn = queue[0];
-			
-		if( fn !== undefined )
-			fn.call(elem);
-	}
-});
-
-jQuery.fn.extend({
-	data: function( key, value ){
-		var parts = key.split(".");
-		parts[1] = parts[1] ? "." + parts[1] : "";
-
-		if ( value === undefined ) {
-			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
-
-			if ( data === undefined && this.length )
-				data = jQuery.data( this[0], key );
-
-			return data === undefined && parts[1] ?
-				this.data( parts[0] ) :
-				data;
-		} else
-			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
-				jQuery.data( this, key, value );
-			});
-	},
-
-	removeData: function( key ){
-		return this.each(function(){
-			jQuery.removeData( this, key );
-		});
-	},
-	queue: function(type, data){
-		if ( typeof type !== "string" ) {
-			data = type;
-			type = "fx";
-		}
-
-		if ( data === undefined )
-			return jQuery.queue( this[0], type );
-
-		return this.each(function(){
-			var queue = jQuery.queue( this, type, data );
-			
-			 if( type == "fx" && queue.length == 1 )
-				queue[0].call(this);
-		});
-	},
-	dequeue: function(type){
-		return this.each(function(){
-			jQuery.dequeue( this, type );
-		});
-	}
-});/*!
- * Sizzle CSS Selector Engine - v0.9.3
- *  Copyright 2009, The Dojo Foundation
- *  Released under the MIT, BSD, and GPL Licenses.
- *  More information: http://sizzlejs.com/
- */
-(function(){
-
-var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
-	done = 0,
-	toString = Object.prototype.toString;
-
-var Sizzle = function(selector, context, results, seed) {
-	results = results || [];
-	context = context || document;
-
-	if ( context.nodeType !== 1 && context.nodeType !== 9 )
-		return [];
-	
-	if ( !selector || typeof selector !== "string" ) {
-		return results;
-	}
-
-	var parts = [], m, set, checkSet, check, mode, extra, prune = true;
-	
-	// Reset the position of the chunker regexp (start from head)
-	chunker.lastIndex = 0;
-	
-	while ( (m = chunker.exec(selector)) !== null ) {
-		parts.push( m[1] );
-		
-		if ( m[2] ) {
-			extra = RegExp.rightContext;
-			break;
-		}
-	}
-
-	if ( parts.length > 1 && origPOS.exec( selector ) ) {
-		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
-			set = posProcess( parts[0] + parts[1], context );
-		} else {
-			set = Expr.relative[ parts[0] ] ?
-				[ context ] :
-				Sizzle( parts.shift(), context );
-
-			while ( parts.length ) {
-				selector = parts.shift();
-
-				if ( Expr.relative[ selector ] )
-					selector += parts.shift();
-
-				set = posProcess( selector, set );
-			}
-		}
-	} else {
-		var ret = seed ?
-			{ expr: parts.pop(), set: makeArray(seed) } :
-			Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
-		set = Sizzle.filter( ret.expr, ret.set );
-
-		if ( parts.length > 0 ) {
-			checkSet = makeArray(set);
-		} else {
-			prune = false;
-		}
-
-		while ( parts.length ) {
-			var cur = parts.pop(), pop = cur;
-
-			if ( !Expr.relative[ cur ] ) {
-				cur = "";
-			} else {
-				pop = parts.pop();
-			}
-
-			if ( pop == null ) {
-				pop = context;
-			}
-
-			Expr.relative[ cur ]( checkSet, pop, isXML(context) );
-		}
-	}
-
-	if ( !checkSet ) {
-		checkSet = set;
-	}
-
-	if ( !checkSet ) {
-		throw "Syntax error, unrecognized expression: " + (cur || selector);
-	}
-
-	if ( toString.call(checkSet) === "[object Array]" ) {
-		if ( !prune ) {
-			results.push.apply( results, checkSet );
-		} else if ( context.nodeType === 1 ) {
-			for ( var i = 0; checkSet[i] != null; i++ ) {
-				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
-					results.push( set[i] );
-				}
-			}
-		} else {
-			for ( var i = 0; checkSet[i] != null; i++ ) {
-				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
-					results.push( set[i] );
-				}
-			}
-		}
-	} else {
-		makeArray( checkSet, results );
-	}
-
-	if ( extra ) {
-		Sizzle( extra, context, results, seed );
-
-		if ( sortOrder ) {
-			hasDuplicate = false;
-			results.sort(sortOrder);
-
-			if ( hasDuplicate ) {
-				for ( var i = 1; i < results.length; i++ ) {
-					if ( results[i] === results[i-1] ) {
-						results.splice(i--, 1);
-					}
-				}
-			}
-		}
-	}
-
-	return results;
-};
-
-Sizzle.matches = function(expr, set){
-	return Sizzle(expr, null, null, set);
-};
-
-Sizzle.find = function(expr, context, isXML){
-	var set, match;
-
-	if ( !expr ) {
-		return [];
-	}
-
-	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
-		var type = Expr.order[i], match;
-		
-		if ( (match = Expr.match[ type ].exec( expr )) ) {
-			var left = RegExp.leftContext;
-
-			if ( left.substr( left.length - 1 ) !== "\\" ) {
-				match[1] = (match[1] || "").replace(/\\/g, "");
-				set = Expr.find[ type ]( match, context, isXML );
-				if ( set != null ) {
-					expr = expr.replace( Expr.match[ type ], "" );
-					break;
-				}
-			}
-		}
-	}
-
-	if ( !set ) {
-		set = context.getElementsByTagName("*");
-	}
-
-	return {set: set, expr: expr};
-};
-
-Sizzle.filter = function(expr, set, inplace, not){
-	var old = expr, result = [], curLoop = set, match, anyFound,
-		isXMLFilter = set && set[0] && isXML(set[0]);
-
-	while ( expr && set.length ) {
-		for ( var type in Expr.filter ) {
-			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
-				var filter = Expr.filter[ type ], found, item;
-				anyFound = false;
-
-				if ( curLoop == result ) {
-					result = [];
-				}
-
-				if ( Expr.preFilter[ type ] ) {
-					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
-
-					if ( !match ) {
-						anyFound = found = true;
-					} else if ( match === true ) {
-						continue;
-					}
-				}
-
-				if ( match ) {
-					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
-						if ( item ) {
-							found = filter( item, match, i, curLoop );
-							var pass = not ^ !!found;
-
-							if ( inplace && found != null ) {
-								if ( pass ) {
-									anyFound = true;
-								} else {
-									curLoop[i] = false;
-								}
-							} else if ( pass ) {
-								result.push( item );
-								anyFound = true;
-							}
-						}
-					}
-				}
-
-				if ( found !== undefined ) {
-					if ( !inplace ) {
-						curLoop = result;
-					}
-
-					expr = expr.replace( Expr.match[ type ], "" );
-
-					if ( !anyFound ) {
-						return [];
-					}
-
-					break;
-				}
-			}
-		}
-
-		// Improper expression
-		if ( expr == old ) {
-			if ( anyFound == null ) {
-				throw "Syntax error, unrecognized expression: " + expr;
-			} else {
-				break;
-			}
-		}
-
-		old = expr;
-	}
-
-	return curLoop;
-};
-
-var Expr = Sizzle.selectors = {
-	order: [ "ID", "NAME", "TAG" ],
-	match: {
-		ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
-		CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
-		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
-		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
-		TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
-		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
-		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
-		PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
-	},
-	attrMap: {
-		"class": "className",
-		"for": "htmlFor"
-	},
-	attrHandle: {
-		href: function(elem){
-			return elem.getAttribute("href");
-		}
-	},
-	relative: {
-		"+": function(checkSet, part, isXML){
-			var isPartStr = typeof part === "string",
-				isTag = isPartStr && !/\W/.test(part),
-				isPartStrNotTag = isPartStr && !isTag;
-
-			if ( isTag && !isXML ) {
-				part = part.toUpperCase();
-			}
-
-			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
-				if ( (elem = checkSet[i]) ) {
-					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
-
-					checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
-						elem || false :
-						elem === part;
-				}
-			}
-
-			if ( isPartStrNotTag ) {
-				Sizzle.filter( part, checkSet, true );
-			}
-		},
-		">": function(checkSet, part, isXML){
-			var isPartStr = typeof part === "string";
-
-			if ( isPartStr && !/\W/.test(part) ) {
-				part = isXML ? part : part.toUpperCase();
-
-				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
-					var elem = checkSet[i];
-					if ( elem ) {
-						var parent = elem.parentNode;
-						checkSet[i] = parent.nodeName === part ? parent : false;
-					}
-				}
-			} else {
-				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
-					var elem = checkSet[i];
-					if ( elem ) {
-						checkSet[i] = isPartStr ?
-							elem.parentNode :
-							elem.parentNode === part;
-					}
-				}
-
-				if ( isPartStr ) {
-					Sizzle.filter( part, checkSet, true );
-				}
-			}
-		},
-		"": function(checkSet, part, isXML){
-			var doneName = done++, checkFn = dirCheck;
-
-			if ( !part.match(/\W/) ) {
-				var nodeCheck = part = isXML ? part : part.toUpperCase();
-				checkFn = dirNodeCheck;
-			}
-
-			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
-		},
-		"~": function(checkSet, part, isXML){
-			var doneName = done++, checkFn = dirCheck;
-
-			if ( typeof part === "string" && !part.match(/\W/) ) {
-				var nodeCheck = part = isXML ? part : part.toUpperCase();
-				checkFn = dirNodeCheck;
-			}
-
-			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
-		}
-	},
-	find: {
-		ID: function(match, context, isXML){
-			if ( typeof context.getElementById !== "undefined" && !isXML ) {
-				var m = context.getElementById(match[1]);
-				return m ? [m] : [];
-			}
-		},
-		NAME: function(match, context, isXML){
-			if ( typeof context.getElementsByName !== "undefined" ) {
-				var ret = [], results = context.getElementsByName(match[1]);
-
-				for ( var i = 0, l = results.length; i < l; i++ ) {
-					if ( results[i].getAttribute("name") === match[1] ) {
-						ret.push( results[i] );
-					}
-				}
-
-				return ret.length === 0 ? null : ret;
-			}
-		},
-		TAG: function(match, context){
-			return context.getElementsByTagName(match[1]);
-		}
-	},
-	preFilter: {
-		CLASS: function(match, curLoop, inplace, result, not, isXML){
-			match = " " + match[1].replace(/\\/g, "") + " ";
-
-			if ( isXML ) {
-				return match;
-			}
-
-			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
-				if ( elem ) {
-					if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
-						if ( !inplace )
-							result.push( elem );
-					} else if ( inplace ) {
-						curLoop[i] = false;
-					}
-				}
-			}
-
-			return false;
-		},
-		ID: function(match){
-			return match[1].replace(/\\/g, "");
-		},
-		TAG: function(match, curLoop){
-			for ( var i = 0; curLoop[i] === false; i++ ){}
-			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
-		},
-		CHILD: function(match){
-			if ( match[1] == "nth" ) {
-				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
-				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
-					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
-					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
-
-				// calculate the numbers (first)n+(last) including if they are negative
-				match[2] = (test[1] + (test[2] || 1)) - 0;
-				match[3] = test[3] - 0;
-			}
-
-			// TODO: Move to normal caching system
-			match[0] = done++;
-
-			return match;
-		},
-		ATTR: function(match, curLoop, inplace, result, not, isXML){
-			var name = match[1].replace(/\\/g, "");
-			
-			if ( !isXML && Expr.attrMap[name] ) {
-				match[1] = Expr.attrMap[name];
-			}
-
-			if ( match[2] === "~=" ) {
-				match[4] = " " + match[4] + " ";
-			}
-
-			return match;
-		},
-		PSEUDO: function(match, curLoop, inplace, result, not){
-			if ( match[1] === "not" ) {
-				// If we're dealing with a complex expression, or a simple one
-				if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
-					match[3] = Sizzle(match[3], null, null, curLoop);
-				} else {
-					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
-					if ( !inplace ) {
-						result.push.apply( result, ret );
-					}
-					return false;
-				}
-			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
-				return true;
-			}
-			
-			return match;
-		},
-		POS: function(match){
-			match.unshift( true );
-			return match;
-		}
-	},
-	filters: {
-		enabled: function(elem){
-			return elem.disabled === false && elem.type !== "hidden";
-		},
-		disabled: function(elem){
-			return elem.disabled === true;
-		},
-		checked: function(elem){
-			return elem.checked === true;
-		},
-		selected: function(elem){
-			// Accessing this property makes selected-by-default
-			// options in Safari work properly
-			elem.parentNode.selectedIndex;
-			return elem.selected === true;
-		},
-		parent: function(elem){
-			return !!elem.firstChild;
-		},
-		empty: function(elem){
-			return !elem.firstChild;
-		},
-		has: function(elem, i, match){
-			return !!Sizzle( match[3], elem ).length;
-		},
-		header: function(elem){
-			return /h\d/i.test( elem.nodeName );
-		},
-		text: function(elem){
-			return "text" === elem.type;
-		},
-		radio: function(elem){
-			return "radio" === elem.type;
-		},
-		checkbox: function(elem){
-			return "checkbox" === elem.type;
-		},
-		file: function(elem){
-			return "file" === elem.type;
-		},
-		password: function(elem){
-			return "password" === elem.type;
-		},
-		submit: function(elem){
-			return "submit" === elem.type;
-		},
-		image: function(elem){
-			return "image" === elem.type;
-		},
-		reset: function(elem){
-			return "reset" === elem.type;
-		},
-		button: function(elem){
-			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
-		},
-		input: function(elem){
-			return /input|select|textarea|button/i.test(elem.nodeName);
-		}
-	},
-	setFilters: {
-		first: function(elem, i){
-			return i === 0;
-		},
-		last: function(elem, i, match, array){
-			return i === array.length - 1;
-		},
-		even: function(elem, i){
-			return i % 2 === 0;
-		},
-		odd: function(elem, i){
-			return i % 2 === 1;
-		},
-		lt: function(elem, i, match){
-			return i < match[3] - 0;
-		},
-		gt: function(elem, i, match){
-			return i > match[3] - 0;
-		},
-		nth: function(elem, i, match){
-			return match[3] - 0 == i;
-		},
-		eq: function(elem, i, match){
-			return match[3] - 0 == i;
-		}
-	},
-	filter: {
-		PSEUDO: function(elem, match, i, array){
-			var name = match[1], filter = Expr.filters[ name ];
-
-			if ( filter ) {
-				return filter( elem, i, match, array );
-			} else if ( name === "contains" ) {
-				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
-			} else if ( name === "not" ) {
-				var not = match[3];
-
-				for ( var i = 0, l = not.length; i < l; i++ ) {
-					if ( not[i] === elem ) {
-						return false;
-					}
-				}
-
-				return true;
-			}
-		},
-		CHILD: function(elem, match){
-			var type = match[1], node = elem;
-			switch (type) {
-				case 'only':
-				case 'first':
-					while (node = node.previousSibling)  {
-						if ( node.nodeType === 1 ) return false;
-					}
-					if ( type == 'first') return true;
-					node = elem;
-				case 'last':
-					while (node = node.nextSibling)  {
-						if ( node.nodeType === 1 ) return false;
-					}
-					return true;
-				case 'nth':
-					var first = match[2], last = match[3];
-
-					if ( first == 1 && last == 0 ) {
-						return true;
-					}
-					
-					var doneName = match[0],
-						parent = elem.parentNode;
-	
-					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
-						var count = 0;
-						for ( node = parent.firstChild; node; node = node.nextSibling ) {
-							if ( node.nodeType === 1 ) {
-								node.nodeIndex = ++count;
-							}
-						} 
-						parent.sizcache = doneName;
-					}
-					
-					var diff = elem.nodeIndex - last;
-					if ( first == 0 ) {
-						return diff == 0;
-					} else {
-						return ( diff % first == 0 && diff / first >= 0 );
-					}
-			}
-		},
-		ID: function(elem, match){
-			return elem.nodeType === 1 && elem.getAttribute("id") === match;
-		},
-		TAG: function(elem, match){
-			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
-		},
-		CLASS: function(elem, match){
-			return (" " + (elem.className || elem.getAttribute("class")) + " ")
-				.indexOf( match ) > -1;
-		},
-		ATTR: function(elem, match){
-			var name = match[1],
-				result = Expr.attrHandle[ name ] ?
-					Expr.attrHandle[ name ]( elem ) :
-					elem[ name ] != null ?
-						elem[ name ] :
-						elem.getAttribute( name ),
-				value = result + "",
-				type = match[2],
-				check = match[4];
-
-			return result == null ?
-				type === "!=" :
-				type === "=" ?
-				value === check :
-				type === "*=" ?
-				value.indexOf(check) >= 0 :
-				type === "~=" ?
-				(" " + value + " ").indexOf(check) >= 0 :
-				!check ?
-				value && result !== false :
-				type === "!=" ?
-				value != check :
-				type === "^=" ?
-				value.indexOf(check) === 0 :
-				type === "$=" ?
-				value.substr(value.length - check.length) === check :
-				type === "|=" ?
-				value === check || value.substr(0, check.length + 1) === check + "-" :
-				false;
-		},
-		POS: function(elem, match, i, array){
-			var name = match[2], filter = Expr.setFilters[ name ];
-
-			if ( filter ) {
-				return filter( elem, i, match, array );
-			}
-		}
-	}
-};
-
-var origPOS = Expr.match.POS;
-
-for ( var type in Expr.match ) {
-	Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
-}
-
-var makeArray = function(array, results) {
-	array = Array.prototype.slice.call( array );
-
-	if ( results ) {
-		results.push.apply( results, array );
-		return results;
-	}
-	
-	return array;
-};
-
-// Perform a simple check to determine if the browser is capable of
-// converting a NodeList to an array using builtin methods.
-try {
-	Array.prototype.slice.call( document.documentElement.childNodes );
-
-// Provide a fallback method if it does not work
-} catch(e){
-	makeArray = function(array, results) {
-		var ret = results || [];
-
-		if ( toString.call(array) === "[object Array]" ) {
-			Array.prototype.push.apply( ret, array );
-		} else {
-			if ( typeof array.length === "number" ) {
-				for ( var i = 0, l = array.length; i < l; i++ ) {
-					ret.push( array[i] );
-				}
-			} else {
-				for ( var i = 0; array[i]; i++ ) {
-					ret.push( array[i] );
-				}
-			}
-		}
-
-		return ret;
-	};
-}
-
-var sortOrder;
-
-if ( document.documentElement.compareDocumentPosition ) {
-	sortOrder = function( a, b ) {
-		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
-		if ( ret === 0 ) {
-			hasDuplicate = true;
-		}
-		return ret;
-	};
-} else if ( "sourceIndex" in document.documentElement ) {
-	sortOrder = function( a, b ) {
-		var ret = a.sourceIndex - b.sourceIndex;
-		if ( ret === 0 ) {
-			hasDuplicate = true;
-		}
-		return ret;
-	};
-} else if ( document.createRange ) {
-	sortOrder = function( a, b ) {
-		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
-		aRange.selectNode(a);
-		aRange.collapse(true);
-		bRange.selectNode(b);
-		bRange.collapse(true);
-		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
-		if ( ret === 0 ) {
-			hasDuplicate = true;
-		}
-		return ret;
-	};
-}
-
-// Check to see if the browser returns elements by name when
-// querying by getElementById (and provide a workaround)
-(function(){
-	// We're going to inject a fake input element with a specified name
-	var form = document.createElement("form"),
-		id = "script" + (new Date).getTime();
-	form.innerHTML = "<input name='" + id + "'/>";
-
-	// Inject it into the root element, check its status, and remove it quickly
-	var root = document.documentElement;
-	root.insertBefore( form, root.firstChild );
-
-	// The workaround has to do additional checks after a getElementById
-	// Which slows things down for other browsers (hence the branching)
-	if ( !!document.getElementById( id ) ) {
-		Expr.find.ID = function(match, context, isXML){
-			if ( typeof context.getElementById !== "undefined" && !isXML ) {
-				var m = context.getElementById(match[1]);
-				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
-			}
-		};
-
-		Expr.filter.ID = function(elem, match){
-			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
-			return elem.nodeType === 1 && node && node.nodeValue === match;
-		};
-	}
-
-	root.removeChild( form );
-})();
-
-(function(){
-	// Check to see if the browser returns only elements
-	// when doing getElementsByTagName("*")
-
-	// Create a fake element
-	var div = document.createElement("div");
-	div.appendChild( document.createComment("") );
-
-	// Make sure no comments are found
-	if ( div.getElementsByTagName("*").length > 0 ) {
-		Expr.find.TAG = function(match, context){
-			var results = context.getElementsByTagName(match[1]);
-
-			// Filter out possible comments
-			if ( match[1] === "*" ) {
-				var tmp = [];
-
-				for ( var i = 0; results[i]; i++ ) {
-					if ( results[i].nodeType === 1 ) {
-						tmp.push( results[i] );
-					}
-				}
-
-				results = tmp;
-			}
-
-			return results;
-		};
-	}
-
-	// Check to see if an attribute returns normalized href attributes
-	div.innerHTML = "<a href='#'></a>";
-	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
-			div.firstChild.getAttribute("href") !== "#" ) {
-		Expr.attrHandle.href = function(elem){
-			return elem.getAttribute("href", 2);
-		};
-	}
-})();
-
-if ( document.querySelectorAll ) (function(){
-	var oldSizzle = Sizzle, div = document.createElement("div");
-	div.innerHTML = "<p class='TEST'></p>";
-
-	// Safari can't handle uppercase or unicode characters when
-	// in quirks mode.
-	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
-		return;
-	}
-	
-	Sizzle = function(query, context, extra, seed){
-		context = context || document;
-
-		// Only use querySelectorAll on non-XML documents
-		// (ID selectors don't work in non-HTML documents)
-		if ( !seed && context.nodeType === 9 && !isXML(context) ) {
-			try {
-				return makeArray( context.querySelectorAll(query), extra );
-			} catch(e){}
-		}
-		
-		return oldSizzle(query, context, extra, seed);
-	};
-
-	Sizzle.find = oldSizzle.find;
-	Sizzle.filter = oldSizzle.filter;
-	Sizzle.selectors = oldSizzle.selectors;
-	Sizzle.matches = oldSizzle.matches;
-})();