Bug 1050477 - Remove mcMerge files now they've moved to Github
authorEd Morley <emorley@mozilla.com>
Fri, 20 Mar 2015 21:33:43 +0000
changeset 1515 5507d424a28314232997ede1eada264320752796
parent 1514 e6720cf640e18dab8bab4ad4a0ccf9b281f458a3
child 1516 73ad7a52c30e515418b0449c630b5d63e8e4bccf
push id876
push useremorley@mozilla.com
push dateFri, 20 Mar 2015 21:34:10 +0000
bugs1050477
Bug 1050477 - Remove mcMerge files now they've moved to Github The mcMerge repo is now at: https://github.com/mozilla/mcMerge And mcMerge is (for now) hosted at: https://mcmerge.paas.allizom.org/
js/Config.js
mcmerge/LICENSE
mcmerge/README.md
mcmerge/css/opensans.woff
mcmerge/css/style.css
mcmerge/images/background.png
mcmerge/images/holly.png
mcmerge/images/sky.png
mcmerge/images/snowy.jpg
mcmerge/index.html
mcmerge/js/BugData.js
mcmerge/js/Config.js
mcmerge/js/ConfigurationData.js
mcmerge/js/DebugUI.js
mcmerge/js/FlagLoader.js
mcmerge/js/PushData.js
mcmerge/js/Remapper.js
mcmerge/js/Step.js
mcmerge/js/Summary.js
mcmerge/js/UI.js
mcmerge/js/Utils.js
mcmerge/js/Viewer.js
mcmerge/js/ViewerController.js
mcmerge/js/mcMerge.js
mcmerge/thirdparty/bzjs/bz-0.3.0.js
mcmerge/thirdparty/jquery/MIT-LICENSE.txt
mcmerge/thirdparty/jquery/jquery-1.7.2.min.js
mcmerge/thirdparty/toast/grid.css
mcmerge/thirdparty/toast/reset.css
mcmerge/thirdparty/toast/toast.css
mcmerge/thirdparty/toast/type.css
--- a/js/Config.js
+++ b/js/Config.js
@@ -21,26 +21,26 @@ var Config = {
   prodBaseURL: "https://tbpl.mozilla.org/", // used for log links in tbplbot bugzilla comments
   mercurialURL: "https://hg.mozilla.org/",
   buildjsonURL: "https://secure.pub.build.mozilla.org/builddata/buildjson/",
   buildapiURL: "https://secure.pub.build.mozilla.org/buildapi/",
   selfServeURL: "https://secure.pub.build.mozilla.org/buildapi/self-serve/",
   slaveHealthURL: "https://secure.pub.build.mozilla.org/builddata/reports/slave_health/slave.html?name=",
   buildGraphsURL: "http://builddata.pub.build.mozilla.org/reports/pending/",
   treeStatusURL: "https://treestatus.mozilla.org/",
-  mcMergeURL: "mcmerge/",
+  mcMergeURL: "https://mcmerge.paas.allizom.org/",
   // treeInfo gives details about the trees and repositories. There are various
   // items that can be specified:
   //
   // - primaryRepo:    [required] The primary hg repository for the tree.
   // - otherRepo:      [optional] An additional hg repository that the tree
   //                              works with.
   //
   // Note that changes to the trees below will likely need similar changes to
-  // mcmerge/js/Config.js as well.
+  // mcmerge as well.
   treeInfo: {
     "Mozilla-Central": {
       primaryRepo: "mozilla-central",
       buildbotBranch: "mozilla-central",
     },
     "Mozilla-Inbound": {
       primaryRepo: "integration/mozilla-inbound",
       buildbotBranch: "mozilla-inbound",
@@ -559,18 +559,16 @@ var Config = {
 };
 
 // Fix up paths when running from the local filesystem
 if (window.location.protocol == "file:") {
   // Default to the production TBPL backend unless we've overidden
   // at the top of this file.
   if (!Config.serverBaseURL)
     Config.serverBaseURL = Config.prodBaseURL;
-  // Fix up mcMerge links
-  Config.mcMergeURL += 'index.html';
 }
 
 Config.clientAbsoluteURL = document.location.href.replace(/\/[^\/]+$/, '/');
 Config.serverAbsoluteURL = Config.serverBaseURL || Config.clientAbsoluteURL;
 
 Config.resultNames = {};
 (function() {
   for (var b in Config.buildNames) {
deleted file mode 100644
--- a/mcmerge/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 Graeme McCutcheon <graememcc_firefox@graeme-online.co.uk> and contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
deleted file mode 100644
--- a/mcmerge/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-mcMerge is a tool for marking bugs post-merge.
-
-NOTES ON TESTING
-----------------
-Adding "?debug=1" shows how all changesets were identified, and shows what changesets mcMerge decided were affected by a backout.
-
-Adding "?remap=1" allows you to divert output to the bzapi sandbox bugzilla at [landfill.bugzilla.org](https://://landfill.bugzilla.org/bzapi_sandbox/).
-If you use this option, you will be presented with a table of all the bugs associated with changesets. You can then enter a bug number from bzapi that output will be sent to. You don't need to enter a new bug number for every single bug shown, but only those you do enter will be transmitted, other bugs will be ignored.
-
-mcMerge will not check the existence of any bugs you enter - be careful! Each bug number entered must be unique - that **will** be checked, as apparently I can't follow my own instructions. You will probably want to review the pushlog - if the push for the only bug you entered was backed out, then nothing will be sent.
-
-When testing target milestone setting, the equivalent bug in landfill must be filed in the *mcMerge Test Product* product, or the submission will fail.
-
-There are various checkbox options at the bottom of the screen:
-* an option to add [inbound] to some random bug whiteboards, to allow you to test it's removal on submission
-* an option to add checkin-needed to some random bug whiteboards, to allow you to test it's removal on submission. Be careful of bugs with additional keywords - if they are not defined on landfill (and they probably won't be), the submission will fail
-* an option to throw up an alert - hacky, I know - partway through the submission process, to allow you to jump over to the landfill bug, and mid-air mcMerge
-* a useful option to ignore the real bug status, and set it to NEW, as you will likely be working with historic pushlogs when testing
-
-If you do not enter any diversion bugs on the remap page, you will return to live mode, with changes going to [bugzilla.mozilla.org](https://bugzilla.mozilla.org/).
-
-
-STANDING ON THE SHOULDERS OF GIANTS
------------------------------------
-mcMerge uses the following third-party projects:
-
-* bz.js by Heather Arthur - [https://github.com/harthur/bz.js](https://github.com/harthur/bz.js)
-* jQuery - [http://jquery.com/](http://jquery.com)
-* Toast CSS framework by Dan Eden - [http://www.daneden.me/toast](http://www.daneden.me/toast)
deleted file mode 100644
index 55b25f867099eb26c436b1c9fecff14a51290d46..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/mcmerge/css/style.css
+++ /dev/null
@@ -1,331 +0,0 @@
-@font-face {
-  font-family: 'Open sans';
-  font-style: normal;
-  font-weight: 400;
-  src: local('Open sans'), url('opensans.woff');
-}
-
-body {
-  background: url(../images/sky.png) 0 0 repeat-x rgb(238, 238, 238);
-  font-family: Georgia, serif;
-  z-index: 1;
-}
-
-h1, h2, h3{
-  color: rgb(72,72,72);
-  font-family: 'Open sans', sans-serif;
-  font-weight: normal;
-}
-
-h1 {
-  font-size: 300%;
-}
-
-h4 {
-  font-size: medium;
-  font-style: italic;
-  font-weight: normal;
-}
-
-a {
-  text-decoration: none;
-  color: #4169e1;
-}
-
-button {
-  font-family: sans-serif;
-  font-size: smaller;
-}
-
-textarea {
-  font-family: monospace;
-  font-size: medium;
-}
-
-table {
-  border-collapse: collapse;
-}
-
-td {
-  border: 1px solid gray;
-  padding-left: 5px;
-  padding-right: 5px;
-  text-align: center;
-}
-
-progress {
-  margin-top: 5px;
-  width: 100%;
-}
-
-.hiddenContent {
-  display: none;
-}
-
-.divRight {
-  text-align: right;
-}
-
-.grid-3.divRight {
-  margin-left: 0px;
-}
-
-.changeset {
-  margin-top: 10px;
-  border: 1px solid black;
-}
-
-.changeset.backedout {
-  margin-top: 0px;
-  margin-bottom: 0px;
-  border-top: 1px solid black;
-  border-left: 1px solid black;
-  border-right: 1px solid black;
-  border-bottom: 0px;
-}
-
-.changeset.backout {
-  margin-top: 0px;
-  margin-bottom: 50px;
-  border-bottom: 1px solid black;
-  border-left: 1px solid black;
-  border-right: 1px solid black;
-  border-top: 0px;
-}
-
-.csetTitle {
-  font-weight: bold;
-  /*font-family: Verdana, sans-serif;*/
-  font-family: 'Open sans', sans-serif;
-  background-color: #87ceeb;
-  color: black;
-  margin-bottom: 10px;
-  padding: 10px;
-}
-
-.csetTitle a:link {
-  color: black;
-  text-decoration: none;
-}
-
-.csetTitle a:visited {
-  color: black;
-}
-
-.csetTitle a:active {
-  color: black;
-}
-
-.csetTitle.backedout {
-  background-color: silver;
-}
-
-.csetTitle.backout {
-  background-color: #87ceeb;
-}
-
-.csetHead {
-  padding-bottom: 10px;
-  background-color: rgb(245, 255, 250);
-}
-
-.files {
-  background-color: rgb(245, 255, 250);
-  padding: 5px 10px 5px 10px;
-  border-top: 1px solid black;
-}
-
-.backoutbanner {
-  font-weight: bold;
-  background-color: rgb(255,239,217);
-  color: red;
-  border: 1px solid black;
-}
-
-.leaveOpen {
-    margin: 5px;
-    padding: 5px;
-    font-size: x-small;
-    background-color: cornsilk;
-    color: green;
-}
-
-.backout {
-  background-color: rgb(255,239,217);
-}
-
-.backout.last {
-  margin-bottom: 0px;
-}
-
-.backoutHeader {
-  color: red; 
-}
-
-.whiteboardTA {
-  width: 100%;
-  border: 1px solid black;
-}
-
-.span.afterWhiteboard {
-  width: 100%;
-}
-
-.grid-6.afterWhiteboard {
-  text-align: right;
-}
-
-.loadingOverlay .ui-dialog-titlebar-close {
-  display: none;
-}
-
-.modal {
-  position: fixed;
-  top: 50%;
-  left: 50%;
-  border: 1px solid black;
-  padding: 5px;
-  -moz-box-sizing: border-box;
-  -ms-box-sizing: border-box;
-  -webkit-box-sizing: border-box;
-  box-sizing: border-box;
-  -moz-transform: translate(-50%, -50%);
-  -ms-transform: translate(-50%, -50%);
-  -webkit-transform: translate(-50%, -50%);
-  transform: translate(-50%, -50%);
-  z-index: 20;
-  background-color: white;
-  font-size: large;
-  width: 300px;
-}
-
-.modalTitle {
-  padding-left: 5px;
-  padding-right: 5px;
-  background-color: #87ceeb;
-}
-
-.modalContent {
-  font-family: "Open Sans", sans-serif;
-  font-size: smaller;
-  padding-left: 5px;
-  padding-right: 5px;
-}
-
-.modalForm {
-  width: 400px;
-}
-
-.modalForm p {
-  margin: 0px 0px 5px 0px;
-}
-
-.modalForm input {
-  font-family: 'Open Sans', sans-serif;
-}
-
-.modalForm button {
-  font-family: 'Open Sans', sans-serif;
-  font-size: large;
-}
-
-.testsuite {
-  font-size: smaller;
-}
-
-#opaque {
-  position: fixed;
-  top: 0;
-  left: 0;
-  bottom: 0;
-  right: 0;
-  opacity: .80;
-  filter: Alpha(Opacity=80); 
-  background-color: rgb(238, 238, 238);
-  background-repeat: repeat-x;
-  background-attachment: scroll;
-  background-position: 50% 50%;
-  z-index: 10;
-}
-
-.bug {
-  padding-top: 5px;
-  padding-bottom: 5px;
-  background-color: white;
-  border-top: 1px solid black;
-}
-
-.bug.resolved {
-  background-color: rgb(245, 255, 250);
-}
-
-.viewhide, .fileviewhide {
-  text-decoration: none;
-  color: #4169e1;
-  cursor: pointer;
-}
-
-.grid-12.commentDiv {
-  display: none;
-  padding-right: 10px;
-}
-
-.comment {
-  width: 100%;
-}
-
-.ctr {
-  text-align: center;
-}
-
-div.ctr {
-  z-index: 5;
-}
-
-.subwarn {
-  color: red;
-}
-
-.prevButton {
-  margin: 10px;
-}
-
-.nextButton {
-  margin: 10px;
-}
-
-.summaryHeading {
-  text-decoration: underline;
-}
-
-#errorText {
-  border: 1px solid rgb(255,213,153);
-  background-color: rgb(255,239,217);
-  color: rgb(51,51,51);
-}
-
-#loadingOverlay {
-  padding-left: 25px;
-}
-
-#loadingOverlayContainer {
-  position: fixed;
-}
-
-#headline, #helpText {
-  margin: 0;
-  padding: 0;
-}
-
-#explanation {
-  width: 100%;
-}
-
-.submitButton {
-  margin-top: 10px;
-}
-
-#expandButton {
-  margin-top: 10px;
-  margin-bottom: 10px;
-}
deleted file mode 100644
index b499bb223e6add15a58abe5bab5da694c9bba585..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 77dbbe4c8b29594792655a6d81c5c158e6bc4293..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index bed0f537a77de74f8c225fad7831a33a53277a92..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index ad3e41e23181de4c98ff70c03bd26abb231967f6..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/mcmerge/index.html
+++ /dev/null
@@ -1,156 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <link type="text/css" rel="stylesheet" href="thirdparty/toast/toast.css" />
-    <link type="text/css" rel="stylesheet" href="css/style.css" />
-    <script type="text/javascript" src="thirdparty/jquery/jquery-1.7.2.min.js"></script>
-    <script type="text/javascript" src="thirdparty/bzjs/bz-0.3.0.js"></script>
-    <script type="text/javascript" src="js/Utils.js"></script>
-    <script type="text/javascript" src="js/Config.js"></script>
-    <script type="text/javascript" src="js/Step.js"></script>
-    <script type="text/javascript" src="js/UI.js"></script>
-    <script type="text/javascript" src="js/DebugUI.js"></script>
-    <script type="text/javascript" src="js/ViewerController.js"></script>
-    <script type="text/javascript" src="js/Viewer.js"></script>
-    <script type="text/javascript" src="js/Summary.js"></script>
-    <script type="text/javascript" src="js/PushData.js"></script>
-    <script type="text/javascript" src="js/FlagLoader.js"></script>
-    <script type="text/javascript" src="js/ConfigurationData.js"></script>
-    <script type="text/javascript" src="js/BugData.js"></script>
-    <script type="text/javascript" src="js/Remapper.js"></script>
-    <script type="text/javascript" src="js/mcMerge.js"></script>
-    <title>mcMerge</title>
-  </head>
-  <body>
-    <div class="hideAll" id="opaque"></div>
-    <div class="ctr">
-      <h1 id="title">mcMerge</h1>
-      <h4>A tool to help with post-merge Bugzilla administrivia. <a href="http://www.graememcc.co.uk/tag/m-cmerge/">Learn more.</a></h4>
-      <div class="hiddenContent hideAll" id="errors">
-        <span id="errorText"></span>
-      </div>
-
-      <div class="hiddenContent hideAll" id="loading"></div>
-
-      <div class="hiddenContent hideAll" id="getCset">
-        <p id="formText">
-          Please enter the URL or hex changeset ID of a changeset from the merge:
-        </p>
-        <form id="csetForm">
-          <input type="text" id="changeset" autofocus />
-          <input type="submit" value="Submit" id="revSubmit" />
-        </form>
-      </div>
-
-      <div class="hiddenContent hideAll" id="detail"></div>
-
-    </div>
-
-    <div class="wrap">
-      <div class="grids">
-        <div class="hiddenContent hideAll" id="viewerOutput"></div>
-        <div class="hiddenContent hideAll" id="pushes"></div>
-      </div>
-    </div>
-
-    <div class="modal hideAll" id="loadingModal">
-      <div id="lmTitle" class="modalTitle">Loading...</div>
-      <div id="lmContent" class="modalContent">
-        Please wait
-      </div>
-    </div>
-
-    <div class="modal hideAll" id="progressModal">
-      <div id="pmTitle" class="modalTitle">Working...</div>
-      <div id="pmContent" class="modalContent">
-        <div class="ctr"><span id="progressText">0</span>% complete</div>
-        <progress max="100" value="0" id="progressBar">
-        </progress>
-      </div>
-    </div>
-
-    <div class="modal modalForm hideAll" id="addBugModal">
-      <div id="abTitle" class="modalTitle">Add bug</div>
-      <div id="abContent" class="modalContent">
-        <form id="addBugForm">
-          <p>
-           Enter the bug number you wish to add:<br />
-          <input type="text" name="Bug number" id="loadBug" />
-          </p>
-          <div class="divRight">
-            <input type="submit" value="Add"/>
-            <button id="abCancel">Cancel</button>
-          </div>
-        </form>
-      </div>
-    </div>
-
-    <div class="modal modalForm hideAll" id="changeBugModal">
-      <div id="cbTitle" class="modalTitle">Change bug</div>
-      <div id="cbContent" class="modalContent">
-        <form id="changeBugForm">
-          <p>
-           Enter a new bug number:<br />
-          <input type="text" name="Bug number" id="changeBug" />
-          </p>
-          <div class="divRight">
-            <input type="submit" value="Change"/>
-            <button id="cbCancel">Cancel</button>
-          </div>
-        </form>
-      </div>
-    </div>
-
-    <div class="modal modalForm hideAll" id="explanationModal">
-      <div id="exTitle" class="modalTitle">Add explanation for backout</div>
-      <div id="exContent" class="modalContent">
-        <form id="explanationForm">
-          <p>
-           Enter explanatory text for this backout:<br />
-          <textarea name="Bug number" id="explanation"></textarea><br />
-          <label for="useForAll">
-            <input type="checkbox" id="useForAll" checked="checked" />
-            Prepend this text to all remaining backout comments
-          </label>
-          </p>
-          <div class="divRight">
-            <input type="submit" value="OK"/>
-            <button id="exCancel">Cancel</button>
-          </div>
-        </form>
-      </div>
-    </div>
-
-    <div class="modal modalForm hideAll" id="credentialsModal">
-      <div id="crTitle" class="modalTitle">Enter your Bugzilla credentials</div>
-      <div id="crContent" class="modalContent">
-        <form id="credentialsForm">
-          <p>Please provide your bugzilla login:<br />
-          Username: <input type="email" name="username" id="username" /><br />
-          Password: <input type="password" name="password" id="password" />
-          </p>
-          <div class="divRight">
-            <input type="submit" value="Submit"/>
-            <button id="crCancel">Cancel</button>
-          </div>
-        </form>
-      </div>
-    </div>
-
-    <div class="modal modalForm hideAll" id="messageModal">
-      <div id="mmTitle" class="modalTitle">Whoops!</div>
-      <div id="mmContent" class="modalContent">
-          <p id="mmText">
-          </p>
-          <div class="divRight">
-            <button id="mmOK">OK</button>
-          </div>
-      </div>
-    </div>
-
-    <noscript>
-      You need Javascript to proceed.
-    </noscript>
-  </body>
-</html>
deleted file mode 100644
--- a/mcmerge/js/BugData.js
+++ /dev/null
@@ -1,137 +0,0 @@
-"use strict";
-
-var BugData = {
-  bugs: {},
-  trackingFlag: null,
-  statusFlag: null,
-  fields: 'id,resolution,status,whiteboard,keywords,target_milestone,summary,product,component,flags,assigned_to',
-  notYetLoaded: [],
-  loadCallback: null,
-  errorCallback: null,
-  checkComments: false,
-
-  load: function BD_load(bugs, checkComments, loadCallback, errorCallback) {
-    this.notYetLoaded = bugs;
-    this.loadCallback = loadCallback;
-    this.errorCallback = errorCallback;
-    this.checkComments = checkComments;
-    this.loadMore();    
-  },
-
-
-  loadMore: function BD_loadMore() {
-    var batch = [];
-    var limit = 500; // to avoid URI too long errors from BZAPI
-    if (this.notYetLoaded.length < limit)
-      limit = this.notYetLoaded.length;
-    for (var i = 0; i < limit; i++)
-      batch.push(this.notYetLoaded.pop());
-    this._realLoad(batch.join(','));
-  },
-
-
-  _realLoad: function BD_realLoad(bugs) {
-    if (mcMerge.trackingFlag)
-      this.trackingFlag = 'cf_' + mcMerge.trackingFlag;
-    if (mcMerge.statusFlag)
-      this.statusFlag = 'cf_' + mcMerge.statusFlag;
-
-    var includeFields = this.fields;
-    if (this.checkComments)
-      includeFields += ',comments';
-    if (this.trackingFlag)
-      includeFields += ',' + this.trackingFlag;
-    if (this.statusFlag)
-      includeFields += ',' + this.statusFlag;
-
-    // Calculate an appropriate timeout for the amount of bugs being loaded
-    var timeout = (Math.floor(bugs.length / 100) + 1) * 30000;
-    bugs = {id : bugs, include_fields: includeFields};
-
-    var self = this;
-    var callback  = function BD_LoadCallback(errmsg, data) {
-      if (errmsg)
-        self.errorCallback(errmsg);
-      else
-        self.parseData(data);
-    };
-
-    var bugzilla = bz.createClient({timeout: timeout});
-    bugzilla.searchBugs(bugs, callback);
-  },
-
-
-  makeBug: function BD_makeBug(bugObj) {
-    var bug = {};
-
-    if (bugObj.resolution)
-      bug.resolution = UI.htmlEncode(bugObj.resolution);
-    else
-      bug.resolution = '';
-    
-    if (bugObj.whiteboard)
-      bug.whiteboard = bugObj.whiteboard;
-    else
-      bug.whiteboard = '';
-
-    if (bugObj.keywords)
-      bug.keywords = bugObj.keywords;
-    else
-      bug.keywords = [];
-
-    // The next five should always be present
-    bug.status = UI.htmlEncode(bugObj.status);
-    bug.milestone = UI.htmlEncode(bugObj.target_milestone);
-    bug.summary = UI.htmlEncode(bugObj.summary);
-    bug.product = bugObj.product;
-    bug.id = bugObj.id;
-    if (typeof bug.id == 'string')
-      bug.id = UI.htmlEncode(bug.id);
-
-    if (this.checkComments)
-      bug.comments = bugObj.comments;
-
-    bug.canResolve = !(bug.status == 'RESOLVED' || bug.status == 'VERIFIED');
-    bug.canReopen = bug.resolution == 'FIXED';
-
-    // The preferred way to prevent bug closure is through the keyword, however
-    // test for the previous method of whiteboard annotation
-    bug.leaveOpen = bug.keywords.indexOf('leave-open') !== -1 ||
-                    Config.leaveOpenRE.test(bug.whiteboard);
-
-    bug.isTracked = false;
-    if (this.trackingFlag && bugObj[this.trackingFlag] == '+')
-      bug.isTracked = true;
-
-    bug.statusFlag = '---';
-    if (this.statusFlag)
-      bug.statusFlag = bugObj[this.statusFlag];
-
-    bug.isUnassigned = bugObj.assigned_to.name == 'nobody';
-
-    bug.intestsuite = ' ';
-    bug.testsuiteFlagID = -1;
-    bug.canSetTestsuite = ConfigurationData.hasTestsuiteFlag[bug.product][bugObj.component];
-    if (bug.canSetTestsuite && 'flags' in bugObj && bugObj.flags) {
-      for (var i = 0; i < bugObj.flags.length; i++) {
-        var f = bugObj.flags[i];
-        if (f.name == 'in-testsuite' && f.type_id == ConfigurationData.testsuiteFlagID) {
-          bug.intestsuite = f.status; 
-          bug.testsuiteFlagID = f.id;
-          break;
-        }
-      }
-    }
-
-    this.bugs[bugObj.id] = bug;
-  },
-
-
-  parseData: function BD_parseData(data, loadCallback) {
-    data.forEach(this.makeBug, this);
-    if (this.notYetLoaded.length == 0)
-      this.loadCallback();
-    else
-      this.loadMore();
-  }
-};
deleted file mode 100644
--- a/mcmerge/js/Config.js
+++ /dev/null
@@ -1,264 +0,0 @@
-"use strict";
-
-var Config = {
-  supportsHistory : !!(window.history && history.pushState),
-  inMaintenanceMode : false,
-
-  treeName: 'mozilla-central',
-  hgBaseURL: "https://hg.mozilla.org/",
-  hgURL: "https://hg.mozilla.org/mozilla-central/",
-  hgRevURL: "https://hg.mozilla.org/mozilla-central/rev/",
-  hgPushlogURL: "https://hg.mozilla.org/mozilla-central/pushloghtml?changeset=",
-  showBugURL: "https://bugzilla.mozilla.org/show_bug.cgi?id=",
-
-  // Here be dragons
-  versionRE: /^mozilla\d+$/i,
-  csetInputRE: /^(tip|[\da-f]{12,40})$/i,
-  csetIDRE: /\b([\da-f]{12,40})\b/ig,
-  leaveOpenRE: /(?:leave|keep)(?:-|\s+)open/i,
-  bugNumRE: /\b(\d{4,7})\b/g,
-  strictBugNumRE: /^(\d{4,7})$/,
-  mergeRE: /\bmerg(ed?|ing)\b/i,
-  backoutRE: /back(ing|ed)?\s*out/i,
-  revertRE: /revert(ing)?/i,
-  partialRevertRE: /(?:from|in)(?:\s+(?:rev(?:ision)?|c(?:hange)?set))?\s+([\da-f]{12,40})/i,
-  partialTestRE: /test\s+for/i,
-  revertRangeRE: /revert(?:ing)?\s+(?:\S+\s+)?to(?:\s+(?:rev(?:ision)?|c(?:hange)set))?\s+([\da-f]{12,40})/i,
-  csetRangeRE: /\b([\da-f]{12,40})\s*(?:to|:|-|through)\s*([\da-f]{12,40})/i,
-  hgRevRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\//ig,
-  hgRevFullRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\/[\da-f]{12}/ig,
-  hgPushlogRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/pushloghtml\?changeset=/ig,
-  emailRE: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,   // I'm not looking for RFC 822 compliance here!
-
-  // The many ways bug numbers are specified
-  bugRE1: /b(?:ug)?=(\d{4,7})\b/i,                       // e.g. b=XXXXXX
-  bugRE2: /^fix(?:es)?\s*(?:for\s*)?(\d{4,7})\b/i,                         // Fix is sometimes used as a synonym for bug
-  bugRE3: /to\s+fix\s+bug\s+(\d{4,7})/i,
-  bugRE4: /\((\d{4,7}), r=/i,                          // e.g. JS-team style (XXXXXX, r=foo)
-  bugRE5: /but\s*(\d{4,7})/i,                          // The typo but XXXXXX happens quite often
-  bugRE6: /\bb(?:u?g(?:zilla)?)?:?\s*#?(\d{4,7})\b/i,  // The catchall
-  bugRE7: /^(\d{4,7})\b/i,                              // e.g. XXXXXX,
-
-  repoMergeRE: "\\s+(&|and|with|<->|<>|-?->|(in|on)?to)\\s+",
-
-  mcSynonyms: ["mozilla-central", "central", "m-c", "mc", "mozilla central"],
-
-  rewriteTrees: {
-    "thunderbird-trunk": "comm-central",
-    "thunderbird-aurora": "comm-aurora",
-    "thunderbird-beta": "comm-beta",
-    "thunderbird-esr31": "comm-esr31",
-    "thunderbird-esr24": "comm-esr24",
-  },
-
-  treeInfo: {
-    "mozilla-central": {
-      repo: "mozilla-central",
-      trackedTree: true,
-      unconditionalFlag: false,
-      synonyms: ["mozilla-central", "central", "m-c", "mc", "mozilla central"]
-    },
-    "b2g-inbound": {
-      repo: "integration/b2g-inbound",
-      trackedTree: false,
-      unconditionalFlag: false,
-      synonyms: ["b2g-inbound", "b-i", "bi"]
-    },
-    "mozilla-inbound": {
-      repo: "integration/mozilla-inbound",
-      trackedTree: false,
-      unconditionalFlag: false,
-      synonyms: ["mozilla-inbound", "inbound", "m-i", "mi"]
-    },
-    "mozilla-aurora": {
-      repo: "releases/mozilla-aurora",
-      trackedTree: true,
-      unconditionalFlag: false,
-      synonyms: ["releases/mozilla-aurora", "mozilla-aurora"]
-    },
-    "mozilla-beta": {
-      repo: "releases/mozilla-beta",
-      trackedTree: true,
-      unconditionalFlag: false,
-      synonyms: ["releases/mozilla-beta", "mozilla-beta"]
-    },
-    "mozilla-release": {
-      repo: "releases/mozilla-release",
-      trackedTree: true,
-      unconditionalFlag: false,
-      synonyms: ["releases/mozilla-release", "mozilla-release"]
-    },
-    "mozilla-esr31": {
-      repo: "releases/mozilla-esr31",
-      trackedTree: true,
-      unconditionalFlag: false,
-      synonyms: ["esr31", "releases/mozilla-esr31", "mozilla-esr31"]
-    },
-    "mozilla-b2g34-v2.1": {
-      repo: "releases/mozilla-b2g34_v2_1",
-      unconditionalFlag: true,
-      trackedTree: true,
-      synonyms: ["b2g34", "mozilla-b2g34", "mozilla-b2g34_v2_1", "v2.1"]
-    },
-    "mozilla-b2g32-v2.0": {
-      repo: "releases/mozilla-b2g32_v2_0",
-      unconditionalFlag: true,
-      trackedTree: true,
-      synonyms: ["b2g32", "mozilla-b2g32", "mozilla-b2g32_v2_0", "v2.0"]
-    },
-    "mozilla-b2g30-v1.4": {
-      repo: "releases/mozilla-b2g30_v1_4",
-      unconditionalFlag: true,
-      trackedTree: true,
-      synonyms: ["b2g30", "mozilla-b2g30", "mozilla-b2g30_v1_4", "v1.4"]
-    },
-    "jetpack": {
-      repo: "projects/addon-sdk",
-      trackedTree: false,
-      unconditionalFlag: false,
-      synonyms: ["projects/addon-sdk", "addon-sdk"]
-    },
-    "fx-team": {
-      repo: "integration/fx-team",
-      trackedTree: false,
-      unconditionalFlag: false,
-      synonyms: ["fx-team"],
-      additions: "[fixed-in-fx-team]"
-    },
-    "ux": {
-      unconditionalFlag: false,
-      repo: "projects/ux",
-      synonyms: ["ux", "projects/ux"]
-    },
-    "alder": {
-      repo: "projects/alder",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["alder", "projects/alder"]
-    },
-    "ash": {
-      repo: "projects/ash",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["ash", "projects/ash"]
-    },
-    "cedar": {
-      repo: "projects/cedar",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/cedar", "cedar"]
-    },
-    "cypress": {
-      repo: "projects/cypress",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/cypress", "cypress"]
-    },
-    "date": {
-      repo: "projects/date",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/date", "date"]
-    },
-    "elm": {
-      repo: "projects/elm",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/elm", "elm"]
-    },
-    "fig": {
-      repo: "projects/fig",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/fig", "fig"],
-      additions: "[fixed-in-fig]"
-    },
-    "gum": {
-      repo: "projects/gum",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/gum", "gum"]
-    },
-    "holly": {
-      repo: "projects/holly",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/holly", "holly"]
-    },
-    "jamun": {
-      repo: "projects/jamun",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/jamun", "jamun"]
-    },
-    "larch": {
-      repo: "projects/larch",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/larch", "larch"]
-    },
-    "maple": {
-      repo: "projects/maple",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/maple", "maple"]
-    },
-    "oak": {
-      repo: "projects/oak",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/oak", "oak"]
-    },
-    "pine": {
-      repo: "projects/pine",
-      unconditionalFlag: false,
-      trackedTree: false,
-      synonyms: ["projects/pine", "pine"]
-    },
-    "comm-central": {
-      repo: "comm-central",
-      unconditionalFlag: false,
-      trackedTree: true,
-      synonyms: ["comm-central", "c-c"]
-    },
-    "comm-aurora": {
-      repo: "releases/comm-aurora",
-      unconditionalFlag: false,
-      trackedTree: true,
-      synonyms: ["releases/comm-aurora", "comm-aurora"]
-    },
-    "comm-beta": {
-      repo: "releases/comm-beta",
-      unconditionalFlag: false,
-      trackedTree: true,
-      synonyms: ["releases/comm-beta", "comm-beta"]
-    },
-    "comm-esr31": {
-      repo: "releases/comm-esr31",
-      unconditionalFlag: false,
-      trackedTree: true,
-      synonyms: ["releases/comm-esr31", "comm-esr31"]
-    }
-  }
-};
-
-Config.bugNumberREs = [Config.bugRE1, Config.bugRE2, Config.bugRE3,
-                       Config.bugRE4, Config.bugRE5, Config.bugRE6, Config.bugRE7];
-
-(function () {
-  var base = Config.hgBaseURL;
-  for (var treeName in Config.treeInfo) {
-    var repo = Config.treeInfo[treeName].repo; 
-    Config.treeInfo[treeName]['hgURL'] = base + repo + '/';
-    Config.treeInfo[treeName]['hgRevURL'] = base + repo + '/rev/';
-    Config.treeInfo[treeName]['hgPushlogURL'] = base + repo + '/pushloghtml?changeset=';
-    Config.treeInfo[treeName]['hgRevRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/', 'ig');
-    Config.treeInfo[treeName]['hgRevFullRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/[\\da-f]{12}', 'ig');
-    Config.treeInfo[treeName]['hgPushlogRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/pushloghtml\\?changeset=', 'ig');
-  }
-})();
-
-// Detect input type="email" support
-$(document).ready(function() {
-  Config.needsValidation = $('#username').prop('type') != 'email';
-});
deleted file mode 100644
--- a/mcmerge/js/ConfigurationData.js
+++ /dev/null
@@ -1,91 +0,0 @@
-"use strict";
-
-var ConfigurationData = {
-  milestones: {},
-  hasTestsuiteFlag: {},
-  testsuiteFlagID: -1,
-
-  // useNext represents products where I'm reasonably
-  // confident that the correct milestone is --- + 1
-  useNext: ['Add-on SDK',
-            'Android Background Services',
-            'Core',
-            'Fennec',
-            'Firefox',
-            'Firefox for Android',
-            'Firefox for Metro',
-            'Firefox Health Report',
-            'Loop',
-            'MailNews Core',
-            'Mozilla Localizations',
-            'Mozilla Services',
-            'Other Applications',
-            'SeaMonkey',
-            'Testing',
-            'Thunderbird',
-            'Toolkit'],
-
-
-  init: function CD_init(loadCallback, errorCallback) {
-    var self = this;
-    var callback  = function CD_initCallback(errmsg, data) {
-      if (errmsg)
-        errorCallback(errmsg);
-      else
-        self.parseData(data, loadCallback);
-    };
-
-    var bugzilla = bz.createClient({timeout: 30000});
-    bugzilla.getConfiguration(callback);
-  },
-
-
-  parseData: function CD_parseData(data, loadCallback) {
-    if (!('product' in data)) {
-        loadCallback();
-        return;
-    }
-    // Find the flag number for in-testsuite
-    if ('flag_type' in data) {
-      for (var flagNumber in data['flag_type']) {
-        if (data['flag_type'][flagNumber].name == 'in-testsuite') {
-          this.testsuiteFlagID = parseInt(flagNumber);
-          break;
-        }
-      }
-    }
-    var products = data.product;
-    var productMilestones = {}
-    for (var product in products) {
-      // Parse Milestones
-      var active_milestones = products[product].target_milestone_detail.filter(function (milestone) {
-        return milestone.is_active;
-      }).map(function (milestone) {
-        return milestone.name;
-      });
-      productMilestones[product] = {}
-      productMilestones[product].values = active_milestones.map(UI.htmlEncode);
-      var dashIndex = active_milestones.indexOf('---');
-      if (dashIndex != -1) {
-        if (dashIndex + 1 < active_milestones.length && this.useNext.indexOf(product) != -1) {
-          productMilestones[product].defaultIndex = dashIndex + 1;
-        } else {
-          productMilestones[product].defaultIndex = dashIndex;
-        }
-      } else {
-        productMilestones[product].defaultIndex = 0;
-      }
-
-      // Find which products/components can have in-testsuite set
-      if (this.testsuiteFlagID != -1) {
-        this.hasTestsuiteFlag[product] = {};
-        for (var component in products[product].component) {
-          var hasTestsuite = products[product].component[component].flag_type.indexOf(this.testsuiteFlagID) != -1;
-          this.hasTestsuiteFlag[product][component] = hasTestsuite;
-        }
-      }
-    }
-    this.milestones = productMilestones;
-    loadCallback();
-  }
-};
deleted file mode 100644
--- a/mcmerge/js/DebugUI.js
+++ /dev/null
@@ -1,42 +0,0 @@
-var DebugUI = {
-  makePushHTML: function UI_makePushHTML(index) {
-    var push = PushData.allPushes[index];
-    var html = '<div class="changeset">';
-    html += '<div class="grid-2">';
-    html += UI.linkifyChangeset(push.cset) + "</div>";
-    html += '<div class="grid-12">' + UI.linkifyDescription(push.desc);
-    html  += ' (Bug ' + UI.linkifyBug(push.bug) + ')';
-    html += ' Index: ' + index;
-    if (push.backedOut)
-      html += ' backed out by ' + UI.linkifyChangeset(push.backedOut);
-    html += "</div>";
-    if ('affected' in push && push.affected) {
-      html += '<div class="grid-12">Affected: ';
-      for (var x in push.affected)
-        html += push.affected[x] +", ";
-      html += '</div>';
-    }
-    html += "</div>";
-    return html;
-  },
-
-
-  makeSection: function DebugUI_makeSection(title, pushes, debug) {
-    var html = '<h3>' + title;
-    html += ' (' + pushes.length + ' changesets)';
-    html += '</h3>';
-    html += pushes.map(this.makePushHTML, this).join('');
-    return html;
-  },
-
-
-  displayPushes: function DebugUI_displayPushes() {
-    var types = ['fixes', 'backedOut', 'foundBackouts', 'notFoundBackouts', 'merges', 'others'];
-    var headings = ['Fixed Bugs', 'Pushes Backed Out', 'Backouts', 'Backouts of things not in this merge',
-                    'Merge Changesets', 'Other Changesets'];
-
-    var pushHTML = types.map(function (val, i) {return this.makeSection(headings[i], PushData[val]);}, this).join('');
-    $('#pushes').html(pushHTML);
-    UI.show('pushes');
-  }
-}
deleted file mode 100644
--- a/mcmerge/js/FlagLoader.js
+++ /dev/null
@@ -1,58 +0,0 @@
-"use strict";
-
-var FlagLoader = {
-
-  init: function FL_init(cset, tree, loadCallback, errorCallback) {
-    // The version for some repositories is a constant, since they're release branches.
-    // We can infer their version from the repo name to avoid querying the repo.
-    var esrVersion = /-esr(\d+)$/.exec(tree);
-    if (esrVersion) {
-      var esrName = 'esr';
-      if (tree.indexOf('comm') != -1) {
-        esrName = 'thunderbird_esr';
-      }
-      var flags = this.generateFlags(esrName + esrVersion[1]);
-      loadCallback(flags);
-      return;
-    }
-    if (tree.indexOf('mozilla-b2g') != -1) {
-      // TODO: B2G repos use B2G version numbers, which are not yet supported.
-      errorCallback(null, 'unknown tree');
-      loadCallback({});
-      return;
-    }
-    var treeInfo = Config.treeInfo[tree];
-    var productName = 'firefox';
-    var fileLocation = '/browser/config/version.txt';
-    if (tree.indexOf('comm') != -1) {
-      productName = 'thunderbird';
-      fileLocation = '/mail/config/version.txt';
-    }
-    var self = this;
-    $.ajax({
-      url: Config.hgBaseURL + treeInfo.repo + '/raw-file/' + cset + fileLocation,
-      dataType: 'text',
-      success: function FL_ajaxSuccessCallback(data) {
-        self.parseData(data, productName, loadCallback, errorCallback);
-      },
-      error: errorCallback
-    });
-  },
-
-  parseData: function FL_parseData(data, productName, loadCallback, errorCallback) {
-    // The version number is of form: "36.0a1", "35.0a2, "34.0" etc.
-    var version = /^([1-9][\d]*)(?:\.[\d]+)?/.exec(data);
-    if (!version) {
-      errorCallback(null, 'Unable to parse version.txt');
-      loadCallback({});
-      return;
-    }
-    var flags = this.generateFlags(productName + version[1]);
-    loadCallback(flags);
-  },
-
-  generateFlags: function FL_generateFlags(flagSuffix) {
-    return {'tracking': 'tracking_' + flagSuffix,
-            'status': 'status_' + flagSuffix};
-  }
-};
deleted file mode 100644
--- a/mcmerge/js/PushData.js
+++ /dev/null
@@ -1,523 +0,0 @@
-"use strict";
-
-var PushData = {
-  // All pushes in sequential order
-  allPushes: [],
-
-  // All normal pushes
-  fixes: [],
-
-  // Backout pushes where the things they back out are in this merge
-  foundBackouts: [],
-
-  // Pushes that were backed out by an entry in foundBackouts
-  backedOut: [],
-
-  // Backout pushes where the things they back out are not in this merge
-  notFoundBackouts: [],
-
-  // All "merge" changesets
-  merges: [],
-
-  // Pushes with no bug number
-  others: [],
-
-  tip: null,
-
-
-  clear: function PD_clear() {
-    this.allPushes = [];
-    this.foundBackouts = [];
-    this.fixes = [];
-    this.merges = [];
-    this.backedOut = [];
-    this.notFoundBackouts = [];
-    this.others = [];
-  },
-
-
-  init: function PD_init(cset, loadCallback, errorCallback) {
-    this.clear();
-    var self = this;
-    $.ajax({
-      url: Config.hgURL + 'json-pushes?full=1&changeset=' + cset,
-      dataType: 'json',
-      timeout: 30000,
-      success: function PD_ajaxSuccessCallback(data) {
-        self.parseData(data, loadCallback);
-      },
-      error: errorCallback
-    });
-  },
-
-
-  // Check whether to handle backouts
-  safeToReopen: function PD_safeToReopen() {
-    return this.fixes.length == 0 && this.backedOut.length == 0 && this.foundBackouts.length == 0;
-  },
-
-
-  // Make a naive attempt at guessing the bug number from the push's description
-  getBugNumber: function PD_getBugNumber(push) {
-    // How shall I specify a bug number?
-    // Let me count the ways...
-    var len = Config.bugNumberREs.length;
-    for (var i = 0; i < len; i++) {
-      var re = Config.bugNumberREs[i];
-      var reResult = re.exec(push.desc);
-
-      if (reResult) {
-        push.bug = reResult[1];
-        break;
-      }
-    }
-  },
-
-
-  // Parse the push description to see if it's a merge push;
-  // mark it as such and clear the bug number if it is
-  checkIfMerge: function PD_checkIfMerge(push) {
-    // The fun here is deciding whether this is a bug whose description
-    // includes the word "merge",
-    //   e.g. "Bug 718255 - Merge nsIPrefBranch2 with nsIPrefBranch - Part A"
-    // or a merge that happens to include a bug number
-    //   e.g "backout merge for bug 724310. r=irc"
-    // I use this heuristic: if the bug number appears before "merge"
-    // then it's a bug, otherwise it's a merge. This will still get some cases
-    // wrong where the bug number follows the bug description, and said description
-    // contains the word "merge"
-    //   e.g "Mostly cosmetic arm merges, merge ARM fcmp(e)d changes (522403, r=graydon)"
-    // but such cases are sufficiently rare to not be worth worrying about
-    var reResult = Config.mergeRE.exec(push.desc);
-    if (!reResult) {
-      push.isMerge = false;
-      return;
-    }
-
-    if (!push.bug) {
-      push.isMerge = true;
-      return;
-    }
-
-    var mergeIndex = reResult.index;
-    var bugIndex = push.desc.indexOf(push.bug);
-    if (bugIndex < mergeIndex) {
-      push.isMerge = false;
-      return;
-    }
-
-    push.isMerge = true;
-    delete push.bug;
-  },
-
-
-  // Parse the push description to see if it's a backout push;
-  // mark it as such and clear the bug number if it is
-  // Note: checkIfBackout assumes checkIfMerge has already been called
-  checkIfBackout: function PD_checkIfBackout(push) {
-    // Get a list of all csets in the description
-    var descCsets = []
-    Config.csetIDRE.lastIndex = 0;
-    var csetRERes;
-    while (csetRERes = Config.csetIDRE.exec(push.desc)) {
-      descCsets.push(csetRERes[1]);
-    }
-
-    // "Merge backout" and "backout merge" are merges, not backouts
-    // However, look for csets that are not already backed out
-    // (ie "Merge backout of X" should follow "backout of X" and can be regarded as a merge
-    // See merge e7d5dd9efeca cset d0c677daedff for a cset that would otherwise have been
-    // incorrectly determined to be a merge
-    if (push.isMerge) {
-      if (descCsets.length == 0) {
-        push.isBackout = false;
-        return;
-      }
-
-      var csetFound = false;
-      for (var i = 0; i < descCsets.length; i++) {
-        var cset = descCsets[i];
-        if (cset.length > 12)
-          cset = cset.substring(0,12);
-        if (cset in this._csets && !this.allPushes[this._csets[cset]].backedOut)
-          csetFound = true;
-      }
-      if (!csetFound) {
-        push.isBackout = false;
-      } else {
-        push.isBackout = true;
-        push.isMerge = false;
-      }
-      return;
-    }
-
-    var reResult = Config.backoutRE.exec(push.desc);
-
-    // If "backout" didn't match, try "revert"
-    if (!reResult) {
-      reResult = Config.revertRE.exec(push.desc);
-
-      // Watch out for partial reverts, eg  "revert accidental change in cset"
-      // Don't classify them as backouts
-      if (reResult) {
-        var reResult2 = Config.partialRevertRE.exec(push.desc);
-        if (reResult2)
-          reResult = null;
-      }
-
-      if (!reResult) {
-        push.isBackout = false;
-        return;
-      }
-    }
-
-    var backoutIndex = reResult.index;
-
-    // The backout may just have been identified in cset terms
-    if (!push.bug) {
-      push.isBackout = true;
-      return;
-    }
-
-    // If there were csets in the description, we can be pretty sure it's
-    // some kind of backout - we only need to decide whether to delete the
-    // bug number to allow the push to be correctly classified
-    if (descCsets.length > 0)
-      push.isBackout = true;
-
-    // From here on, we know there is a bug number in the message, as
-    // push.bug is set. Gather up all the bug numbers in the desc
-    var descBugs = []
-    Config.bugNumRE.lastIndex = 0;
-    var bugRERes;
-    while (bugRERes = Config.bugNumRE.exec(push.desc)) {
-      descBugs.push(bugRERes[1]);
-    }
-
-    var bugIndex = push.desc.indexOf(push.bug);
-    if (bugIndex > backoutIndex) {
-      // "Backout" appears before the bug number, so we can be pretty confident
-      // that this is a backout.
-      delete push.bug;
-
-      // However, there is one more thing to test: look for "test for" before the
-      // bug number. In that case, we're only backing out the test, not the fix
-      Config.partialTestRE.lastIndex = 0;
-      reResult = Config.partialTestRE.exec(push.desc);
-      if (reResult) {
-        var testIndex = reResult.index;
-        if (testIndex < bugIndex) {
-          push.isBackout = false;
-          return;
-        }
-      }
-      push.isBackout = true;
-      return;
-    }
-
-    // Having reached this point, the bug number is before the backout text. This makes
-    // things...interesting.
-    // - If the bug number matches an earlier push, assume it's a backout of said push
-    // - If there's more than one bug number in the description, and those other bugs are
-    //     earlier in the push, mark them as backed out
-    // - Otherwise, it's a bug tracker tracked bug
-
-    // Check to see if we've already had a push with this bug number. (At this point, this
-    // push is not yet in this._bugs). Only consider this a backout if there is one previous
-    // push with this bug number, and there isn't anything claiming it was backed out.
-    if (descBugs.length == 1) {
-      if (push.bug in this._bugs && this._bugs[push.bug].length == 1 &&
-          !this.allPushes[this._bugs[push.bug][0]].backedOut) {
-        delete push.bug;
-        push.isBackout = true;
-      } else {
-        // Only 1 bug number? Looks like we've picked up a random commit with backout in message
-        push.isBackout = false;
-        return;
-      }
-    }
-
-    // More than 1 bug number is likely a backout, but the bug number before the word backout is
-    // likely to be the bug number tracking the backout rather than the thing backed out
-    push.isBackout = true;
-    return;
-  },
-
-
-  // "Applies" or reverses the effect of the specified backout
-  // i.e if reverse is false, it sets the backedOut property on the
-  // affected changesets, and applies/reverses any of those changesets
-  // that themselves are backouts
-  actionBackout: function PD_actionBackout(push, reverse) {
-    if (!push.isBackout || push.affected.length == 0)
-      return;
-
-    var cset = push.cset;
-    var affected = push.affected;
-    var len = affected.length
-
-    // Safest to go backwards
-    for (var i = push.affected.length - 1; i >= 0; i--) {
-      var p = this.allPushes[affected[i]];
-      if (!reverse)
-        p.backedOut = cset;
-      else
-        delete p.backedOut;
-
-      if (p.isBackout)
-        this.actionBackout(p, !reverse);
-    }
-  },
-
-
-  // Calculates the indices in this.allPushes of changesets affected by this
-  // backout. Adds an "affected" property to the backout, which is an array
-  // of said indices
-  buildBackoutAffectedList: function PD_backoutAffectedList(push) {
-    function chop(cset) {
-      if ((typeof cset == 'string') && cset.length > 12)
-        cset = cset.substr(0,12);
-      return cset;
-    }
-
-    if (!push.isBackout)
-      return;
-
-    var desc = push.desc;
-    var cset = push.cset;
-
-    push.affected = new Array();
-
-    // Look for "revert to" messages
-    var reResult = Config.revertRangeRE.exec(desc);
-    if (reResult) {
-      var floor = chop(reResult[1]);
-      if (!floor)
-        return;
-
-      // The csets are backed out are the one immediately following floor, and up to
-      // and including the cset immediately prior to this one
-      if (!(floor in this._csets && cset in this._csets))
-        return;
-
-      var lower = this._csets[floor] + 1;
-      var upper = this._csets[cset];
-      for (var i = lower; i < upper; i++)
-        // Don't let backouts affect merges
-        if (!this.allPushes[i].isMerge)
-          push.affected.push(i);
-      return;
-    }
-
-    // Backouts can sometimes be specified by a cset range
-    // e.g aaabbbcccddd to eeefff000111 or 222333444555:666777888999
-    // This is similar to the "revert to" situation above
-    reResult = Config.csetRangeRE.exec(desc);
-    if (reResult) {
-      var bound1 = chop(reResult[1]);
-      var bound2 = chop(reResult[2]);
-      if (!bound1 || !bound2)
-        return;
-
-      if (!(bound1 in this._csets && bound2 in this._csets))
-        return;
-
-      // Two key differences from the "revert to" logic above:
-      // Bounds are inclusive, and we shouldn't assume an ordering of the two changesets
-      var lower = this._csets[bound1];
-      var upper = this._csets[bound2];
-      if (upper < lower) {
-        var temp = upper;
-        upper = lower;
-        lower = temp;
-      }
-
-      for (var i = lower; i <= upper; i++)
-        // Don't let backouts affect merges
-        if (!this.allPushes[i].isMerge)
-          push.affected.push(i);
-      return;
-    }
-
-    // Now try looking for individual changeset IDs
-    var hadChangesets = false;
-
-
-    Config.csetIDRE.lastIndex = 0;
-    while (reResult = Config.csetIDRE.exec(desc)) {
-      hadChangesets = true;
-      var outCset = chop(reResult[0]);
-      if (outCset in this._csets)
-        // Don't let backouts affect merges
-        if (!this.allPushes[this._csets[outCset]].isMerge && push.affected.indexOf(this._csets[outCset]) == -1)
-          push.affected.push(this._csets[outCset]);
-    }
-
-    // Don't look for bug numbers if description included
-    // changesets: any bug numbers are likely to refer to the
-    // same changesets
-    if (hadChangesets) {
-      push.affected.sort(function compare(a, b) {
-        return a - b;
-      });
-      return;
-    }
-
-    Config.bugNumRE.lastIndex = 0;
-    while (reResult = Config.bugNumRE.exec(desc)) {
-      var bug = reResult[0];
-      // Ignore the bug number if it matches the push bug number
-      if (bug == push.bug)
-        continue;
-
-      // If we have this bug, any pushes with this bug number will have had their
-      // indices in pushes added to this._bugs
-      if (this._bugs[bug]) {
-        var bugPushes = this._bugs[bug];
-
-        for (var i = 0; i < bugPushes.length; i++) {
-          if (!this.allPushes[bugPushes[i]].isMerge && push.affected.indexOf(bugPushes[i]) == -1)
-            push.affected.push(bugPushes[i]);
-        }
-      }
-    }
-  },
-
-
-  // Do a second check for merge backouts - if we have two sequential backouts which both
-  // claim to affect the same changeset, then the second is a merge backout
-  postBackoutMergeCheck: function PD_postBackoutMergeCheck(push) {
-    push.affected.sort(function compare(a, b) {
-      return a - b;
-    });
-
-    // Now, do a check for merge backouts that don't have the word
-    // "merge" in them. If every affected changeset is also affected
-    // by the immediately preceding changeset, then this is a merge
-    if (push.affected.length == 0 || this.allPushes.length < 2 || !this.allPushes[this.allPushes.length - 2].isBackout)
-      return;
-
-    var prevAffected = this.allPushes[this.allPushes.length - 2].affected;
-    if (!prevAffected || prevAffected.length < push.affected.length)
-      return;
-
-    var allInPrevious = true;
-    for (var i = 0; i < push.affected.length; i++) {
-      if (prevAffected.indexOf(push.affected[i]) == -1)
-        allInPrevious = false;
-    }
-
-    if (!allInPrevious)
-      return;
-
-    push.isBackout = false;
-    delete push.affected;
-    delete push.bug;
-    push.isMerge = true;
-  },
-
-
-  // Create a push object, and flag it as a merge or backout if necessary
-  makePush: function PD_makePush(cset) {
-    var push = {};
-    push.cset = cset.node.substring(0,12);
-    push.hgLink = Config.hgRevURL + push.cset;
-    // Only use the first line of the commit message, to avoid false
-    // positives when checking for bug numbers and backouts later.
-    push.desc = UI.htmlEncode(cset.desc.split('\n', 1)[0]);
-    push.files = cset.files;
-
-    var author = cset.author;
-    var index = author.indexOf(' <');
-    if (author.indexOf(' <') != -1) {
-      var emailEnd = author.indexOf('>');
-      push.email = author.substring(index + 2, emailEnd);
-      author = author.substr(0, index);
-    } else
-      push.email = author;
-    push.author = UI.htmlEncode(author);
-
-    // Have a stab at working out the bug number. This will return the first possibility
-    // it finds - which may not in fact be the bug number! It may also turn out to be the
-    // tip of a merge, or the bug number of the bug backed out by this changeset
-    this.getBugNumber(push);
-
-    // Flag various "special" pushes. Order is important here:
-    // checkIfBackout assumes merges have already been flagged as such
-    this.checkIfMerge(push);
-    this.checkIfBackout(push);
-    return push;
-  },
-
-
-  // Given a cset, make a push, and add it to the appropriate array
-  createPushFromCset: function PD_createPushFromCset(cset) {
-    var push = this.makePush(cset);
-    var index = this.allPushes.push(push) - 1;
-    // Note where this cset is in case buildBackoutAffectedList needs to find it
-    this._csets[push.cset] = index;
-
-    if (push.bug) {
-      if (!this._bugs[push.bug])
-        this._bugs[push.bug] = new Array();
-       var len = this._bugs[push.bug].push(index);
-
-      if (push.isBackout) {
-        this.buildBackoutAffectedList(push);
-        this.postBackoutMergeCheck(push);
-      }
-    } else if (push.isBackout) {
-        this.buildBackoutAffectedList(push);
-        this.postBackoutMergeCheck(push);
-    }
-
-    // postBackoutMergeCheck may have removed the backout flag
-    if (push.isBackout)
-        this.actionBackout(push, false);
-  },
-
-
-  // Classifies each push, and inserts into the appropriate array
-  classifyPushes: function PD_classifyPush(push, index) {
-    if (push.isMerge)
-      this.merges.push(index);
-    else if (push.bug && !push.backedOut && !push.isBackout)
-      this.fixes.push(index);
-    else if (push.backedOut)
-      this.backedOut.push(index);
-    else if (push.isBackout && push.affected && push.affected.length > 0)
-      this.foundBackouts.push(index);
-    else if (push.isBackout && push.affected && push.affected.length == 0)
-      this.notFoundBackouts.push(index);
-    else
-      this.others.push(index);
-  },
-
-
-  parseData: function PD_parseData(data, loadCallback) {
-    // Maps csets to their indices in pushes
-    this._csets = new Array();
-
-    // Maps bug numbers to their indices in pushes
-    this._bugs = new Array();
-
-    for (var c in data) {
-      var changesets = data[c].changesets;
-      changesets.forEach(this.createPushFromCset, this);
-    }
-
-    this.allPushes.forEach(this.classifyPushes, this);
-
-    this.foundBackouts.reverse();
-    this.fixes.reverse();
-    this.merges.reverse();
-    this.backedOut.reverse();
-    this.notFoundBackouts.reverse();
-    this.others.reverse();
-
-    delete this._csets;
-    delete this._bugs;
-
-    loadCallback();
-  }
-};
deleted file mode 100644
--- a/mcmerge/js/Remapper.js
+++ /dev/null
@@ -1,221 +0,0 @@
-"use strict";
-
-// The "remapper" will be shown when using the right incantation in the query string.
-// It is an unsophisticated debug/testing shim, to allow submissions to be sent to
-// the bzapi_sandbox bugzilla on landfill.bugzilla.org. Note that each unique real bug
-// must be mapped to a unique landfill bug. If testing target milestone setting, the bug
-// must be filed in the 'mcMerge Test Product' component.
-//
-// You do not have to supply a new bug number for every bug: however, only the bugs you
-// have specified a new bug number for will be submitted.
-//
-// If you don't specify any, you will drop in to normal mode, and the changes will go
-// to bugzilla.mozilla.org
-var Remapper = {
-
-  makeHTMLForBug: function rm_makeHTMLForBug(id) {
-    var html = '<div class="grid-half">Remap bug for bug ' + id + '</div>';
-    html += '<div class="grid-half"><input id="'+id+'" type="text"></div>';
-    return html;
-  },
-
-
-  makeHTMLForOptions: function rm_makeHTMLForOptions() {
-   var html = '<hr>';
-   html += '<div class="grid-12"><h3>Other options:</h3></div>'
-   html += '<div class="grid-12">Display an alert after fetching last_change_time (to allow you to mid-air the change)';
-   html += '<input type="checkbox" id="midair"></div>';
-   html += '<div class="grid-12">Set bug statuses to NEW (to allow you testing of bug resolution)';
-   html += '<input type="checkbox" id="new"></div>';
-   html += '<div class="grid-12">Add checkin-needed into keywords (to allow testing of checkin-needed removal)';
-   html += '<input type="checkbox" id="checkin"></div>';
-   html += '<div class="grid-12">Add [inbound] into whiteboard (to allow testing of [inbound] removal)';
-   html += '<input type="checkbox" id="inbound"></div>';
-   html += '<div class="grid-12">Add [fixed-in-fx-team] into whiteboard (to allow testing of [fixed-in-fx-team] removal)';
-   html += '<input type="checkbox" id="fxteam"></div>';
-   html += '<div class="grid-12">Ignore comments (i.e. override the "Don\'t duplicate comments" mechanism)';
-   html += '<input type="checkbox" id="comments"></div>';
-   html += '<hr>';
-   return html;
-  },
-
-  makeHTMLForSubmit: function rm_makeHTMLForSubmit() {
-    var html = '<div class="grid-12 divRight" id="remsubmit">';
-    html += '  <button type="button" id="remapSubmit">Submit</button>';
-    html += '</div>';
-    return html;
-  },
-
-
-  onSubmit: function rm_onSubmit() {
-    var remaps = {items: 0};
-
-    for (var b in BugData.bugs) {
-      var val = $("#"+b).val().trim();
-      if (val != '' && Config.strictBugNumRE.test(val)) {
-        remaps[b] = val;
-        remaps.items = remaps.items + 1;
-      }
-    }
-
-    // Double-check that all the remapped bug numbers are unique
-    // in order to counter my own stupidity
-    var rm = [];
-    var count = 0;
-    for (b in remaps) {
-      if (b == 'items')
-        continue;
-      count++;
-      if (rm.indexOf(remaps[b]) == -1)
-        rm.push(remaps[b]);
-    }
-    if (rm.length < count) {
-      this.error("Some redirects are not unique");
-      return;
-    }
-
-    if ($('#new').prop('checked')) {
-      if (remaps.items == 0) {
-        this.error('You need to redirect at least 1 bug for status changing to work!');
-        return;
-      }
-      for (b in remaps) {
-        if (b == 'items')
-          continue;
-        if (b in BugData.bugs) {
-          BugData.bugs[b].status = 'NEW';
-          BugData.bugs[b].resolution = '';
-          BugData.bugs[b].canResolve = true;
-        }
-      }
-    }
-
-    if ($('#checkin').prop('checked')) {
-      if (remaps.items == 0) {
-        this.error('You need to redirect at least 1 bug for checkin-needed to work!');
-        return;
-      }
-      var checkinSingle = false;
-      for (b in remaps) {
-        if (b == 'items')
-          continue;
-        if (b in BugData.bugs) {
-          if (BugData.bugs[b].keywords.length == 0 && checkinSingle == false) {
-            BugData.bugs[b].keywords.push('checkin-needed');
-            checkinSingle = true;
-          }
-        }
-      }
-    }
-
-    if ($('#inbound').prop('checked')) {
-      if (remaps.items == 0) {
-        this.error('You need to redirect at least 1 bug for inbound to work!');
-        return;
-      }
-      var inboundSingle = false;
-      var inboundMultiple = false;
-      for (b in remaps) {
-        if (b == 'items')
-          continue;
-        if (b in BugData.bugs) {
-          if (BugData.bugs[b].whiteboard.length == 0 && inboundSingle == false) {
-            BugData.bugs[b].whiteboard = '[inbound]'
-            BugData.bugs[b].summary += ' [inbound]';
-            inboundSingle = true;
-          } else if (BugData.bugs[b].whiteboard.length > 0 && inboundMultiple == false) {
-            BugData.bugs[b].whiteboard += '[inbound]';
-            BugData.bugs[b].summary += ' [inbound]';
-            inboundMultiple = true;
-          }
-        }
-      }
-    }
-
-    if ($('#fxteam').prop('checked')) {
-      if (remaps.items == 0) {
-        this.error('You need to redirect at least 1 bug for fxteam to work!');
-        return;
-      }
-      var fxteamSingle = false;
-      var fxteamMultiple = false;
-      for (b in remaps) {
-        if (b == 'items')
-          continue;
-        if (b in BugData.bugs) {
-          if (BugData.bugs[b].whiteboard.length == 0 && fxteamSingle == false) {
-            BugData.bugs[b].whiteboard = '[fixed-in-fx-team]'
-            BugData.bugs[b].summary += ' [fixed-in-fx-team]';
-            fxteamSingle = true;
-          } else if (BugData.bugs[b].whiteboard.length > 0 && fxteamMultiple == false) {
-            BugData.bugs[b].whiteboard += '[fixed-in-fx-team]';
-            BugData.bugs[b].summary += ' [fixed-in-fx-team]';
-            fxteamMultiple = true;
-          }
-        }
-      }
-    }
-
-    if ($('#comments').prop('checked')) {
-      for (b in remaps) {
-        if (b == 'items')
-          continue;
-        if (b in BugData.bugs) {
-          BugData.bugs[b].comments = [{text: 'Dummy comment'}];
-        }
-      }
-    }
-
-    if ($('#midair').prop('checked')) {
-      if (remaps.items == 0) {
-        this.error('You need to redirect at least 1 bug for debug midairs to work!');
-        return;
-      }
-      remaps.midair = true;
-    } else
-     remaps.midair = false;
-
-    UI.clearErrorMessage();
-    mcMerge.onRemap(remaps);
-  },
-
-
-  addSubmitListener: function rm_AddSubmitListener() {
-    var self = this;
-    var submitCallback = function rm_AddSubmitCallback(e) {
-      e.preventDefault();
-
-      self.onSubmit();
-    }
-
-    $('#remapSubmit').one('click', submitCallback);
-  },
-
-
-  error: function rm_error(message) {
-    UI.showErrorMessage(message);
-    this.addSubmitListener();
-  },
-
-
-  show: function rm_show() {
-    // Hide any previous viewer output
-    UI.hide("viewerOutput");
-    $("#viewerOutput").empty("");
-
-    var helpText = 'Enter bug numbers from the bzapi_sandbox bugzilla that output for a particular';
-    helpText += ' bug should be redirected to. Please ensure that each bug is mapped to an unique sandbox bug!';
-    helpText += '<br><strong>Note: if you do not supply any redirect bug numbers, you will return to normal mode';
-    helpText += ', and changes will go to bugzilla.mozilla.org!</strong>';
-    $("#viewerOutput").append('<div class="grid-12"><p>' + helpText + '</p></div>');
-
-    for (var b in BugData.bugs)
-      $("#viewerOutput").append(this.makeHTMLForBug(b));
-
-    $("#viewerOutput").append(this.makeHTMLForOptions());
-    $('#viewerOutput').append(this.makeHTMLForSubmit());
-    this.addSubmitListener();
-    UI.show("viewerOutput");
-    $("html")[0].scrollIntoView();
-  }
-}
deleted file mode 100644
--- a/mcmerge/js/Step.js
+++ /dev/null
@@ -1,1053 +0,0 @@
-"use strict";
-
-// Step objects represent a particular set of pushes, eg fixes, merge changesets etc.
-// They encapsulate what bugs are "attached" to a particular changeset - i.e. which
-// bugs should be commented with the url for a particular push, along with the comment to
-// be written for each push/bug combination. A step is also responsible for transmitting the
-// relevant changes to Bugzilla
-function Step(name, callbacks, isBackout) {
-
-  var self = this;
-
-  function constructAttachedBugs(useBackouts) {
-    var arr = PushData[self.name];
-    if (useBackouts)
-      arr = PushData['backedOut'];
-
-    var len = arr.length;
-    for (var i = 0; i < len; i++) {
-      var push = PushData.allPushes[arr[i]];
-      if (push.bug) {
-        self.attachedBugs[arr[i]] = {};
-        self.attachBugToCset(arr[i], push.bug);
-      } else if (push.backoutBugs && push.backoutBugs.length > 0) {
-        self.attachedBugs[arr[i]] = {};
-        var l2 = push.backoutBugs.length;
-        for (var j = 0; j < l2; j++)
-          self.attachBugToCset(arr[i], push.backoutBugs[j]);
-      }
-    }
-  }
-
-  this.name = name;
-  this.callbacks = callbacks;
-  this.hasBackouts = isBackout;
-
-  this.attachedBugs = {};
-  this.bugInfo = {};
-  this.sent = [];
-  this.prependChosen = false;
-  this.prependText = '';
-
-  // The following are used for additional help text
-  this.leaveOpenBugs = [];
-  this.multiBugs = [];
-  this.securityBugs = [];
-  this.hasMilestones = [];
-  this.statusChangeBugs = [];
-  this.haveComment = [];
-
-  var options = {};
-  if (Step.remaps.items > 0)
-    options.test = true;
-  this.unprivilegedLoader = bz.createClient(options);
-
-  constructAttachedBugs(false);
-  if (this.hasBackouts)
-    constructAttachedBugs(true);
-}
-
-
-Step.prototype.getName = function Step_getName() {
-  return this.name;
-};
-
-
-Step.prototype.canSubmit = function Step_canSubmit() {
-  for (var bug in this.bugInfo) {
-    var info = this.bugInfo[bug];
-    if ((info.canResolve && info.shouldResolve))
-      return true;
-  }
-
-  for (var cset in this.attachedBugs) {
-    for (var b in this.attachedBugs[cset]) {
-      var attached = this.attachedBugs[cset][b];
-      if (attached.canComment && attached.shouldComment)
-        return true;
-    }
-  }
-  return false;
-};
-
-
-Step.prototype.getSentData = function Step_getSentData() {
-  return this.sent;
-};
-
-
-Step.prototype.hasSecurityBugs = function Step_hasSecurityBugs() {
-  return this.securityBugs.length > 0;
-};
-
-
-Step.prototype.getSecurityBugs = function Step_getSecurityBugs() {
-  var secBugs = [];
-  for (var cset in this.attachedBugs) {
-    for (var b in this.attachedBugs[cset]) {
-      if (!(b in BugData.bugs))
-        secBugs.push({bug: b, cset: PushData.allPushes[cset].cset, link: PushData.allPushes[cset].hgLink});
-    }
-  }
-  return secBugs;
-};
-
-
-Step.prototype.createComment = function Step_createComment(text) {
-  return {creation_time: new Date().toISOString(),
-          creator: {email: Step.username},
-          is_private: 0,
-          text: text};
-};
-
-
-Step.prototype.createBug = function Step_createBug(bugID, info) {
-  var bug = {};
-  var changed = false;
-
-  if (info.canResolve && info.shouldResolve) {
-    bug.resolution = 'FIXED';
-    bug.status = 'RESOLVED';
-    changed = true;
-    if (info.milestone != '---' && info.milestone != BugData.bugs[bugID].milestone) {
-      bug.target_milestone = info.milestone;
-      bug.product = BugData.bugs[bugID].product;
-    }
-  } else if (info.canReopen && info.shouldReopen) {
-    bug.resolution = '';
-    bug.status = 'REOPENED';
-    changed = true;
-  }
-
-  var comments = [];
-  for (var i = 0; i < info.linkedChangesets.length; i++) {
-    var index = info.linkedChangesets[i];
-    var attached = this.attachedBugs[index][bugID];
-    if (!attached.canComment || !attached.shouldComment)
-      continue;
-    comments.push(attached.comment);
-  }
-
-  if (comments.length > 0) {
-    var text = comments.join('\n');
-    bug.comments = [this.createComment(text)];
-    changed = true;
-  }
-
-  if (changed) {
-    bug.id = bugID;
-
-    bug.whiteboard = BugData.bugs[bugID].whiteboard;
-
-    // Remove checkin-needed if present in keywords
-    var keywords = BugData.bugs[bugID].keywords;
-    var checkinIndex = keywords.indexOf('checkin-needed');
-    if (checkinIndex != -1) {
-      keywords.splice(checkinIndex, 1);
-      bug.keywords = keywords;
-    }
-
-    // Set status flag if appropriate
-    if (info.canSetStatus && info.shouldSetStatus) {
-      var fieldName = 'cf_' + mcMerge.statusFlag;
-      bug[fieldName] = 'fixed';
-    }
-
-    // Set assignee if appropriate
-    if (!BugData.bugs[bugID].leaveOpen && !info.canReopen && !info.shouldReopen &&
-        BugData.bugs[bugID].isUnassigned && info.linkedChangesets.length > 0) {
-      var canSetAssignee = true;
-      var assignee = PushData.allPushes[info.linkedChangesets[0]].email;
-      for (var i = 1; i < info.linkedChangesets.length; i++) {
-        if (PushData.allPushes[info.linkedChangesets[i]].email != assignee) {
-          canSetAssignee = false;
-          break;
-        }
-      }
-      if (canSetAssignee)
-        bug.assigned_to = {name: assignee};
-    }
-
-    // Set in-testsuite if possible 
-    if (BugData.bugs[bugID] && info.canSetTestsuite && info.intestsuite != BugData.bugs[bugID].intestsuite) {
-      bug.flags = [{name: 'in-testsuite',
-                    setter: {email: Step.username},
-                    type_id: ConfigurationData.testsuiteFlagID,
-                    status: info.intestsuite}];
-      if (BugData.bugs[bugID].testsuiteFlagID != -1)
-        bug.flags[0].id = BugData.bugs[bugID].testsuiteFlagID;
-    }
-
-    if (bugID in Step.remaps) {
-      bug.id = Step.remaps[bugID];
-      if ('resolution' in bug)
-        bug.product = 'mcMerge test product';
-    }
-    return bug;
-  }
-
-  return null;
-};
-
-
-Step.prototype.constructData = function Step_constructData() {
-  this.sendData = [];
-  for (var bug in this.bugInfo) {
-    if (Step.remaps.items == 0 || bug in Step.remaps) {
-      var info = this.bugInfo[bug];
-      var data = this.createBug(bug, info);
-
-      if (data)
-        this.sendData.push(data);
-    }
-  }
-};
-
-
-Step.prototype.onSubmitError = function Step_onSubmitError(where, msg, i) {
-  if (where == 'lct' && msg == 'HTTP status 400') {
-    // There are a number of possibilities here:
-    // - an invalid username or password was supplied
-    // - the bug we were trying to load is a security bug (shouldn't happen, unless someone
-    //    changed the bug underneath us after the initial bug data load)
-    // - a tester remapped to a non-existant bug on landfill, (they should know better :))
-    // If we've failed trying to get the time/token on our very first bug, let's just put it
-    //   down to username/password, and abandon this submit attempt
-    // If we failed in the i-1th bug too, again abandon all hope. (Did you change your password while mcMerge was working?!?)
-    // Else, we'll note this one failed and try the next. If we carry on without further failure, then this was a
-    //  security bug that wasn't one before
-    if (i == 0 || this.retries[this.retries.length-1] == i - 1) {
-      // XXX What if we've already succesfully submitted some?
-      delete Step.privilegedLoad;
-      delete Step.privilegedUpdate;
-      delete Step.username;
-      this.retries = [];
-      UI.showErrorMessage('The username or password you supplied was not valid. Submit attempt abandoned.');
-      UI.hideProgressModal();
-      return;
-    }
-    this.retries.push(i);
-    this.continueSubmit(i);
-  }
-  if (where == 'submit' && msg == 'HTTP status 400') {
-    // First check to see if there was an assignee in the data we sent. If so, we should try and submitting again - it may have been a
-    // case where the email was wrong (or the author's bugzilla email is different from the email in the changeset). Don't count that as
-    // a retry
-    if ('assigned_to' in this.sendData[i]) {
-      delete this.sendData[i].assigned_to;
-      this.startSubmit(i);
-      return;
-    }
-  }
-  // If we got a bad request here, either we were mid-aired or something really
-  // odd happened, like the product milestone was deleted. Try again, unless of course this *was* our
-  // retry
-  if (this.retries.length == 0 || this.retries[this.retries.length - 1] != i) {
-    this.retries.push(i);
-    this.startSubmit(i);
-    return;
-  }
-  this.continueSubmit(i);
-};
-
-
-Step.prototype.onSubmit = function Step_onSubmit() {
-  UI.hide('errors');
-  if ((typeof Step.privilegedUpdate == 'undefined') || (typeof Step.username == 'undefined') ||
-      (typeof Step.privilegedLoad == 'undefined'))
-    this.callbacks.credentialsCallback();
-  else
-    this.beginSubmit();
-};
-
-
-Step.prototype.onCredentialsAcquired = function Step_onCredentialsAcquired(username) {
-  this.beginSubmit();
-};
-
-
-Step.prototype.beginSubmit = function Step_beginSubmit() {
-  UI.showProgressModal();
-  this.constructData();
-  this.retries = [];
-  this.successful = 0;
-  this.prependChosen = false;
-  this.prependText = '';
-  if (this.sendData.length == 0) {
-    UI.hideProgressModal();
-    return;
-  }
-
-  this.startSubmit(0);
-};
-
-
-Step.prototype.startSubmit = function Step_startSubmit(i) {
-  var self = this;
-
-  // Offer the chance to add a backout explanation where appropriate
-  if (this.name == 'notFoundBackouts' && 'comments' in this.sendData[i] &&
-      this.sendData[i].comments[0].text.indexOf(Config.hgBaseURL) == 0) {
-    if (this.prependChosen) {
-      this.sendData[i].comments[0].text = this.prependText + this.sendData[i].comments[0].text
-      this.midSubmit(i);
-    } else {
-      var self = this;
-      var callback = function Step_onExplanationAcquired(text, useForAll) {
-        if (useForAll) {
-          self.prependChosen = true;
-          self.prependText = text;
-        }
-        self.sendData[i].comments[0].text = text + self.sendData[i].comments[0].text
-        self.midSubmit(i);
-      };
-      UI.acquireExplanation(callback, this.sendData[i].id);
-    }
-  } else
-    this.midSubmit(i);
-};
-
-
-Step.prototype.midSubmit = function Step_midSubmit(i) {
-  var self = this;
-  var callback = function Step_startSubmitCallback(lct, ut) {
-    self.sendData[i].last_change_time = lct;
-    self.sendData[i].update_token = ut;
-    self.submit(i);
-  };
-  this.getLastChangeAndToken(i, callback);
-};
-
-
-Step.prototype.getLastChangeAndToken = function Step_getLastChangeAndToken(i, callback) {
-  var self = this;
-  var id = this.sendData[i].id;
-  var ourCallback  = function Step_getLCATCallback(errmsg, data) {
-    if (errmsg)
-      self.onSubmitError('lct', errmsg, i, callback);
-    else
-      callback(data.last_change_time, data.update_token);
-  };
-
-  Step.privilegedLoad(id, ourCallback);
-};
-
-
-Step.prototype.submit = function Step_submit(i) {
-  // we start with an utterly unsophisticated hack for debugging/testing
-  if (Step.remaps.items > 0 && Step.remaps.midair)
-    alert('MID-AIR TIME!');
-
-  var self = this;
-  var callback = function Step_submitCallback(errmsg, data) {
-    if (errmsg)
-      self.onSubmitError('submit', errmsg, i, callback);
-    else
-      self.postSubmit(i);
-  };
-
-  Step.privilegedUpdate(this.sendData[i].id, this.sendData[i], callback);
-};
-
-
-Step.prototype.postSubmit = function Step_postSubmit(i) {
-  // If this was a retry, remove it from the retries array - we succeeded!
-  if (this.retries.length > 0 && this.retries[this.retries.length - 1] == i)
-    this.retries.pop();
-
-  this.successful += 1;
-  UI.updateProgressModal(((i+1) * 100)/this.sendData.length);
-
-  var sent = this.sendData[i];
-  delete sent.update_token;
-  this.sent.push(sent);
-  var bugID = sent.id;
-
-  // If we were in remapping mode, we need to reverse the mapping!
-  for (var k in Step.remaps) {
-    if (k == 'items')
-      continue;
-    if (Step.remaps[k] == bugID) {
-      bugID = k;
-      break;
-    }
-  }
-
-  var info = this.bugInfo[bugID];
-
-  // Disallow resolving if we just resolved the bug
-  if ('resolution' in sent) {
-    BugData.bugs[bugID].status = sent.status;
-    BugData.bugs[bugID].resolution = sent.resolution;
-    if ('target_milestone' in sent)
-      BugData.bugs[bugID].milestone = sent.target_milestone;
-    info.canResolve = false;
-    info.shouldResolve = false;
-    BugData.bugs[bugID].canReopen = false;
-    info.canReopen = false;
-  }
-
-
-  // Update the intestsuite flag if we sent it
-  if ('flags' in sent) {
-    info.intestsuite = sent.flags[0].status;
-    BugData.bugs[bugID].intestsuite = sent.flags[0].status;
-  }
-
-  for (var j = 0; j < info.linkedChangesets.length; j++) {
-    var index = info.linkedChangesets[j];
-    // Disallow comments if we just sent a comment
-    if ('comments' in sent) {
-      var attached = this.attachedBugs[index][bugID];
-      if (attached.canComment && attached.shouldComment) {
-        attached.canComment = false;
-        attached.shouldComment = false;
-      }
-    }
-    this.callbacks.uiUpdate(index, bugID);
-  }
-
-  // Disallow setting status- if we just sent it
-  if ('cf_' + mcMerge.statusFlag in sent) {
-    info.canSetStatus = false;
-    info.shouldSetStatus = false;
-    BugData.bugs[bugID].statusFlag = sent['cf_' + mcMerge.statusFlag];
-  }
-
-  this.continueSubmit(i);
-};
-
-
-Step.prototype.continueSubmit = function Step_continueSubmit(i) {
-  if (i + 1 >= this.sendData.length) {
-    UI.updateProgressModal(100);
-    if (this.retries.length > 0) {
-      var ltext = this.retries.map(function(elem) {
-        var bug = this.sendData[elem].id;
-        return 'Bug ' + bug;}, this).join('\n');
-      UI.showErrorMessage('The following bugs failed to submit:\n' + ltext);
-    }
-    window.setTimeout(UI.hideProgressModal, 1000);
-  } else
-    this.startSubmit(i+1);
-};
-
-
-Step.prototype.adjustWhiteboard = function Step_adjustWhiteboard(whiteboard, backingOut) {
-  var newWhiteboard = whiteboard;
-
-  if (Config.treeName == 'mozilla-central' || backingOut) {
-    // It appears some people still do this, so we may as well correct it
-    newWhiteboard = whiteboard.replace('[inbound]','');
-
-    // Remove annotations on fx-team merges
-    newWhiteboard = newWhiteboard.replace(/\[fixed(?:\s+|-)in(?:\s+|-)fx(?:\s+|-)team\]/ig, '');
-
-    // Remove annotations on s-c merges
-    newWhiteboard = newWhiteboard.replace(/\[fixed(?:\s+|-)in(?:\s+|-)services\]/ig, '');
-
-    // Remove annotations on fig merges
-    newWhiteboard = newWhiteboard.replace(/\[fixed(?:\s+|-)in(?:\s+|-)fig\]/ig, '');
-  }
-
-  if ('additions' in Config.treeInfo[Config.treeName]) {
-    var addition = Config.treeInfo[Config.treeName].additions;
-    if (newWhiteboard.indexOf(addition) == -1)
-      newWhiteboard = newWhiteboard + addition;
-  }
-
-  return newWhiteboard;
-};
-
-
-// Update the shouldSetStatus field for a bug
-Step.prototype.checkShouldSetStatus = function Step_checkShouldSetStatus(bugID) {
-  if (!(bugID in this.bugInfo))
-    return
-
-  var info = this.bugInfo[bugID];
-  if (!info.canSetStatus) {
-    info.shouldSetStatus = false; 
-    return;
-  }
-
-  // Basically we want some kind of assertion of the fix to be posted to the bug
-  // That means - for a tracked tree - we should be sending at least one comment.
-  // Additionally, for m-c and c-c we also need to be resolving the bug.
-  if ((Config.treeName == 'mozilla-central' || Config.treeName == 'comm-central')  &&
-      (!info.canResolve || !info.shouldResolve)) {
-    info.shouldSetStatus = false;
-    return;
-  }
-
-  var linked = info.linkedChangesets;
-  var hasComment = false;
-  for (var i = 0; i < info.linkedChangesets.length; i++) {
-    var index = info.linkedChangesets[i];
-    var attached = this.attachedBugs[index][bugID];
-    if (attached.canComment && attached.shouldComment) {
-      hasComment = true;
-      break;
-    }
-  }
-
-  info.shouldSetStatus = hasComment;
-};
-
-
-// Associate a bug number with a particular push
-Step.prototype.attachBugToCset = function Step_attachBugToCset(index, bugID) {
-  var attached = {};
-  var isMC = Config.treeName == 'mozilla-central';
-
-  attached.comment = PushData.allPushes[index].hgLink;
-
-  if (bugID in BugData.bugs) {
-    attached.shouldComment = !(PushData.allPushes[index].backedOut);
-  } else {
-    attached.shouldComment = false;
-  }
-
-  var leaveOpen = false;
-  var milestone = '---';
-  var hasMilestone = false;
-  var bug = BugData.bugs[bugID];
-
-  if (bug) {
-    leaveOpen = bug.leaveOpen;
-    hasMilestone = bug.milestone != '---';
-    if (hasMilestone || leaveOpen || !(Config.treeName == 'mozilla-central' || Config.treeName == 'comm-central'))
-      milestone = bug.milestone;
-    else {
-      var defaultMilestone = ConfigurationData.milestones[bug.product].defaultIndex;
-      milestone = ConfigurationData.milestones[bug.product].values[defaultMilestone];
-    }
-  }
-
-  if (!(bugID in this.bugInfo)) {
-    this.bugInfo[bugID] = {canResolve: bug && bug.canResolve,
-                           shouldResolve: bug && !(PushData.allPushes[index].backedOut) &&
-                                          bug.canResolve && !leaveOpen,
-                           linkedChangesets: [],
-                           canReopen: false,
-                           shouldReopen: false,
-                           canSetStatus: false,
-                           shouldSetStatus: false,
-                           canSetTestsuite: bug && bug.canSetTestsuite,
-                           milestone: milestone};
-
-    // Don't resolve bugs for integration repos
-    if (Config.treeName != 'mozilla-central' && Config.treeName != 'comm-central') {
-      this.bugInfo[bugID].canResolve = false;
-      this.bugInfo[bugID].shouldResolve = false;
-       
-    }
-
-    // Handle backouts when safe to do so
-    if (PushData.safeToReopen() && bug && bug.canReopen) {
-      this.bugInfo[bugID].canReopen = true;
-      this.bugInfo[bugID].shouldReopen = true;
-      attached.shouldComment = true;
-    }
-
-    // Release-tracking: determine if status-[tree]N can be set
-    if (bug && (bug.statusFlag == '---' || bug.statusFlag == 'affected')) {
-      if ((bug.isTracked || bug.statusFlag == "affected") && (isMC || Config.treeName == 'comm-central'))
-        this.bugInfo[bugID].canSetStatus = this.bugInfo[bugID].canResolve;
-      else if (Config.treeInfo[Config.treeName].trackedTree)
-        this.bugInfo[bugID].canSetStatus = true;
-    } else if (bug && Config.treeInfo[Config.treeName].trackedTree && Config.treeInfo[Config.treeName].unconditionalFlag) {
-        bug.isTracked = true;
-        this.bugInfo[bugID].canSetStatus = true;
-    }
-
-    // Allow setting of intestsuite if possible
-    if (bug && bug.canSetTestsuite)
-      this.bugInfo[bugID].intestsuite = bug.intestsuite;
-
-    // Adjust the whiteboard the first time we see this bug
-    if (bug)
-      bug.whiteboard = this.adjustWhiteboard(bug.whiteboard, this.bugInfo[bugID].canReopen);
-  }
-
-  if (bug && bug.comments) {
-    var hasThisComment = false;
-    // Iterate backwards: if commented already, the changeset will be in one of the last comments
-    for (var i = bug.comments.length - 1; i > -1; i--) {
-      if (bug.comments[i].text && bug.comments[i].text.indexOf(attached.comment) != -1) {
-        hasThisComment = true;
-        if (this.haveComment.indexOf(bug.id) == -1)
-          this.haveComment.push(bug.id);
-        break;
-      }
-    }
-    attached.canComment = !hasThisComment;
-  } else if (bug && bug.comments === undefined)
-    attached.canComment = true;
-  else 
-    attached.canComment = false;
-
-  if (!attached.canComment)
-    attached.shouldComment = false;
-
-  // Maintain indices of changesets linked to a particular bug, in order to coalesce comments
-  this.bugInfo[bugID].linkedChangesets.push(index);
-  this.bugInfo[bugID].linkedChangesets.sort(function compare(a, b) {return a-b;});
-
-  if (!(index in this.attachedBugs))
-    this.attachedBugs[index] = {};
-
-  var attachedBugs = this.attachedBugs[index];
-  attachedBugs[bugID] = attached;
-
-  // Release-tracking: determine if status-[tree]N should be set
-  if (bug)
-    this.checkShouldSetStatus(bugID);
-
-  // Various bits of state used for constructing additional help text
-  if (this.bugInfo[bugID].linkedChangesets.length == 2)
-    this.multiBugs.push(bugID);
-  if (this.bugInfo[bugID].canSetStatus && this.bugInfo[bugID].shouldSetStatus &&
-      this.statusChangeBugs.indexOf(bugID) == -1)
-    this.statusChangeBugs.push(bugID);
-  if (!bug && this.securityBugs.indexOf(bugID) == -1)
-    this.securityBugs.push(bugID);
-  if (isMC && leaveOpen && this.leaveOpenBugs.indexOf(bugID) == -1)
-    this.leaveOpenBugs.push(bugID);
-  if (isMC && hasMilestone && this.hasMilestones.indexOf(bugID) == -1 &&
-      this.bugInfo[bugID].canResolve)
-    this.hasMilestones.push(bugID);
-};
-
-
-// Returns an array of strings representing the bug numbers
-// associated with the given push
-Step.prototype.getAttachedBugs = function Step_getAttachedBugs(index) {
-  var result = []
-
-  if (index in this.attachedBugs) {
-    for (var bugID in this.attachedBugs[index])
-      result.push(bugID);
-  }
-
-  return result;
-};
-
-
-// Returns true if the given string bugID representing a bug number
-// is associated with the push at the given index
-Step.prototype.isAttached = function Step_isAttached(index, bugID) {
-  if (!(index in this.attachedBugs))
-    return false;
-  if (!(bugID in this.attachedBugs[index]))
-    return false;
-
-  return true;
-};
-
-
-Step.prototype.updateShouldSetStatusAfterResolve = function Step_updateShouldSetStatusAfterResolve(bugID, should) {
-  function removeFromArr(arr) {
-    var i = arr.indexOf(bugID);
-    if (i == -1)
-      return;
-
-    arr.splice(i, 1);
-  }
-
-  if (!this.bugInfo[bugID].canSetStatus)
-    return;
-
-  // Resolve can't be toggled for aurora/beta etc trees, so if we're here after a resolve toggle
-  // that implies m-c/c-c. Hence, if shouldResolve has been switched off, we can immediately decide
-  // that we can't set the status
-  if (!should) {
-    this.bugInfo[bugID].shouldSetStatus = false;
-    removeFromArr(this.statusChangeBugs);
-    return;
-  }
-
-  this.checkShouldSetStatus(bugID);
-  if (this.bugInfo[bugID].shouldSetStatus && this.statusChangeBugs.indexOf(bugID) == -1)
-    this.statusChangeBugs.push(bugID);
-  else if (!this.bugInfo[bugID].shouldSetStatus)
-    removeFromArr(this.statusChangeBugs);
-};
-
-
-Step.prototype.setShouldResolve = function Step_setShouldResolve(bugID, should) {
-  if (!(bugID in this.bugInfo))
-    return;
-
-  this.bugInfo[bugID].shouldResolve = should;
-  this.updateShouldSetStatusAfterResolve(bugID, should);
-};
-
-
-Step.prototype.toggleShouldResolve = function Step_toggleShouldResolve(bugID) {
-  if (!(bugID in this.bugInfo))
-    return;
-
-  should = this.bugInfo[bugID].shouldResolve;
-  this.bugInfo[bugID].shouldResolve = !should;
-  this.updateShouldSetStatusAfterResolve(bugID, !should);
-};
-
-
-Step.prototype.shouldResolve = function Step_shouldResolve(bugID) {
-  if (!(bugID in this.bugInfo))
-    return false;
-
-  return this.bugInfo[bugID].shouldResolve;
-};
-
-
-Step.prototype.canResolve = function Step_canResolve(bugID) {
-  if (!(bugID in this.bugInfo))
-    return false;
-
-  return this.bugInfo[bugID].canResolve;
-};
-
-
-Step.prototype.shouldReopen = function Step_shouldReopen(bugID) {
-  if (!(bugID in this.bugInfo))
-    return false;
-
-  return this.bugInfo[bugID].shouldReopen;
-};
-
-
-Step.prototype.canReopen = function Step_canReopen(bugID) {
-  if (!(bugID in this.bugInfo))
-    return false;
-
-  return this.bugInfo[bugID].canReopen;
-};
-
-
-Step.prototype.setShouldReopen = function Step_setShouldReopen(bugID, should) {
-  if (!(bugID in this.bugInfo))
-    return;
-
-  this.bugInfo[bugID].shouldReopen = should;
-};
-
-
-Step.prototype.canSetMilestone = function Step_canSetMilestone(bugID) {
-  if (!(bugID in this.bugInfo))
-    return false;
-
-  return this.bugInfo[bugID].canResolve && bugID in BugData.bugs;
-};
-
-
-Step.prototype.getMilestone = function Step_getMilestone(bugID) {
-  if (!(bugID in this.bugInfo))
-    return '---';
-
-  return this.bugInfo[bugID].milestone;
-};
-
-
-Step.prototype.setMilestone = function Step_setMilestone(bugID, newVal) {
-  if (!(bugID in this.bugInfo))
-    return;
-
-  this.bugInfo[bugID].milestone = newVal;
-};
-
-
-Step.prototype.getTestsuite = function Step_getTestsuite(bugID) {
-  if (!(bugID in this.bugInfo))
-    return ' ';
-
-  return this.bugInfo[bugID].intestsuite;
-};
-
-
-Step.prototype.setTestsuite = function Step_setTestsuite(bugID, newVal) {
-  if (!(bugID in this.bugInfo))
-    return;
-
-  this.bugInfo[bugID].intestsuite = newVal;
-};
-
-
-Step.prototype.updateShouldSetStatusAfterComment = function Step_updateShouldSetStatusAfterComment(bugID) {
-  function removeFromArr(arr) {
-    var i = arr.indexOf(bugID);
-    if (i == -1)
-      return;
-
-    arr.splice(i, 1);
-  }
-
-  if (!this.bugInfo[bugID].canSetStatus)
-    return;
-
-  this.checkShouldSetStatus(bugID);
-  if (this.bugInfo[bugID].shouldSetStatus && this.statusChangeBugs.indexOf(bugID) == -1)
-    this.statusChangeBugs.push(bugID);
-  else if (!this.bugInfo[bugID].shouldSetStatus)
-    removeFromArr(this.statusChangeBugs);
-};
-
-
-Step.prototype.setShouldComment = function Step_setShouldComment(index, bugID, should) {
-  if (!this.isAttached(index, bugID))
-    return;
-
-  this.attachedBugs[index][bugID].shouldComment = should;
-  this.updateShouldSetStatusAfterComment(bugID);
-};
-
-
-Step.prototype.shouldComment = function Step_shouldComment(index, bugID) {
-  if (!this.isAttached(index, bugID))
-    return false;
-
-  return this.attachedBugs[index][bugID].shouldComment;
-};
-
-
-Step.prototype.toggleShouldComment = function Step_toggleShouldComment(index, bugID) {
-  if (!this.isAttached(index, bugID))
-    return;
-
-  should = this.attachedBugs[index][bugID].shouldComment;
-  this.attachedBugs[index][bugID].shouldComment = !should;
-  this.updateShouldSetStatusAfterComment(bugID);
-};
-
-
-Step.prototype.setComment = function Step_setComment(index, bugID, comment) {
-  if (!this.isAttached(index, bugID))
-    return;
-
-  this.attachedBugs[index][bugID].comment = comment;
-};
-
-
-Step.prototype.getComment = function Step_getComment(index, bugID) {
-  if (!this.isAttached(index, bugID))
-    return '';
-
-  return this.attachedBugs[index][bugID].comment;
-};
-
-
-Step.prototype.canComment = function Step_canComment(index, bugID) {
-  if (!this.isAttached(index, bugID))
-    return false;
-
-  return this.attachedBugs[index][bugID].canComment;
-};
-
-
-Step.prototype.setWhiteboard = function Step_setWhiteboard(index, bugID, whiteboard) {
-  if (!this.isAttached(index, bugID))
-    return;
-
-  if (bugID in BugData.bugs)
-    BugData.bugs[bugID].whiteboard = whiteboard;
-};
-
-
-Step.prototype.getProp = function Step_getProp(index, bugID, prop) {
-  if (prop == 'shouldResolve')
-    return this.shouldResolve(bugID);
-  if (prop == 'canResolve')
-    return this.canResolve(bugID);
-  if (prop == 'shouldComment')
-    return this.shouldComment(index, bugID);
-  if (prop == 'canComment')
-    return this.canComment(index, bugID);
-  if (prop == 'shouldReopen')
-    return this.shouldReopen(bugID);
-  if (prop == 'canReopen')
-    return this.canReopen(bugID);
-
-  return false;
-};
-
-
-// Disassociate a bug with the changeset at the given index
-Step.prototype.detachBugFromCset = function Step_detachBugFromCset(index, bugID) {
-  if (!this.isAttached(index, bugID))
-    return;
-
-  delete this.attachedBugs[index][bugID]
-  this.bugInfo[bugID].linkedChangesets.splice(this.bugInfo[bugID].linkedChangesets.indexOf(index),1)
-
-  function removeFromArr(arr) {
-    var i = arr.indexOf(bugID);
-    if (i == -1)
-      return;
-
-    arr.splice(i, 1);
-  }
-
-  if (this.bugInfo[bugID].linkedChangesets.length == 0) {
-    removeFromArr(this.securityBugs);
-    removeFromArr(this.leaveOpenBugs);
-    removeFromArr(this.statusChangeBugs);
-    delete this.bugInfo[bugID];
-  } else if (this.bugInfo[bugID].linkedChangesets.length == 1)
-    removeFromArr(this.multiBugs);
-};
-
-
-// Convenience function for constructing correctly pluralised text
-// for the help text, based on the contents of the given array
-Step.prototype.constructTextFor = function Step_constructTextFor(arr, postText, verb, expandAll) {
-  var isare = {singular: 'is', plural: 'are'};
-  verb = verb || isare;
-  expandAll = expandAll || false;
-  var text = '';
-
-  if (arr.length > 0) {
-    var len = arr.length;
-    text += '<br>- ';
-    if (len <= 3 || expandAll) {
-      if (len == 1)
-        text += 'Bug ' + UI.linkifyBug(arr[0]);
-      else  {
-        text += 'Bugs ';
-        for (var i = 0; i < len - 1; i++) {
-          if (i != 0)
-            text += ',';
-          text += ' ' + UI.linkifyBug(arr[i]);
-        }
-        text += ' and ' + UI.linkifyBug(arr[len - 1]);
-      }
-    } else
-      text += 'Several bugs';
-    if (len == 1)
-      text += ' ' + verb.singular;
-    else
-      text += ' ' + verb.plural;
-    text += postText;
-  }
-
-  return text;
-};
-
-
-// Calls out various interesting properties of the attached bugs
-//   - "multi" bugs (where a bug is associated with multiple changesets
-//   - "leave open" bugs (where the assignee doesn't want the bug resolved
-//   - "security" bugs (bugs mcMerge couldn't access)
-//   - "has milestone" bugs (bugs that can be resolved, but already had a milestone)
-Step.prototype.getAdditionalHelpText = function Step_getAdditionalHelpText() {
-  var text = '';
-
-  var multiPost = ' associated with multiple changesets: the individual comments will be coalesced into a single comment.';
-  var leaveOpenPost = ' "leave open" in the whiteboard, so the resolve flag has not been set.';
-  var securityPost = ' restricted - mcMerge was unable to load the relevant information from Bugzilla.';
-  var milestonePost = ' a milestone set. You may wish to check it is correct before submitting.';
-  var alreadyCommentPost = ' to have already been commented with the correct changeset URL, so commenting there has been disabled.';
-  var statusChangePost = ' tracked or uplifted and will have ' + mcMerge.statusFlag + ' set to "fixed".';
-
-  var hashave = {singular: 'has', plural: 'have'};
-  var appearTo = {singular: 'appears', plural: 'appear'};
-  var isare = {singular: 'is', plural: 'are'};
-  var already = {singular: 'already has', plural: 'already have'};
-
-  if (this.multiBugs.length > 0 || this.leaveOpenBugs.length > 0 ||
-      this.securityBugs.length > 0)
-    text += '<br>';
-
-  if (this.multiBugs.length > 0)
-    text += this.constructTextFor(this.multiBugs, multiPost);
-
-  if (this.leaveOpenBugs.length > 0)
-    text += this.constructTextFor(this.leaveOpenBugs, leaveOpenPost, hashave);
-
-  if (this.securityBugs.length > 0)
-    text += this.constructTextFor(this.securityBugs, securityPost);
-
-  if (this.haveComment.length > 0)
-    text += this.constructTextFor(this.haveComment, alreadyCommentPost, appearTo, true);
-
-  if (this.hasMilestones.length > 0)
-    text += this.constructTextFor(this.hasMilestones, milestonePost, already, true);
-
-  if (this.statusChangeBugs.length > 0 && !Config.treeInfo[Config.treeName].unconditionalFlag)
-    text += this.constructTextFor(this.statusChangeBugs, statusChangePost, isare);
-
-  return text;
-};
-
-
-Step.prototype.setStepNumber = function Step_setStepNumber(num) {
-  this.stepNumber = num;
-};
-
-
-Step.prototype.setMaxStepNumber = function Step_setMaxStepNumber(num) {
-  this.maxStepNumber = num;
-};
-
-
-// Return the user-visible step name to be shown for this step
-Step.prototype.getHeading = function Step_getHeading(addMax) {
-  addMax = addMax || true;
-
-  var res = this.name;
-  if (this.name in Step.headings)
-    res = Step.headings[this.name];
-
-  if ('stepNumber' in this) {
-    if (addMax && 'maxStepNumber' in this)
-      res = 'Step ' + this.stepNumber + ' of ' + this.maxStepNumber + ': ' + res;
-    else
-      res = 'Step ' + this.stepNumber + ': ' + res;
-  }
-
-  return res;
-};
-
-
-// Return the user-visible help text to be shown for this step
-Step.prototype.getHelpText = function Step_getHelpText() {
-  var helpText = '';
-  if (this.name in Step.helpTexts)
-    helpText = Step.helpTexts[this.name];
-  helpText += this.getAdditionalHelpText();
-
-  if (this.statusChangeBugs.length > 0 && Config.treeInfo[Config.treeName].unconditionalFlag)
-    helpText += '<br>- Submitted bugs will have ' + mcMerge.statusFlag + ' set to "fixed"';
-
-  if (Step.remaps && 'items' in Step.remaps && Step.remaps.items > 0)
-    helpText += '<br><strong>Note: You are in debug mode. Only remap bugs will be submitted, and will be submitted to landfill.bugzilla.org!</strong>';
-  return helpText;
-};
-
-
-Step.helpTexts=  {
-    fixes: 'The following fixes have landed. Double-check that the bug number has been correctly detected, and the correct comment attached, and that the "Comment" and "Resolve" flags have been correctly set. Click on "Submit" to submit these changes to Bugzilla.',
-    foundBackouts: 'The following pushes appear to have been backed-out, and therefore shouldn\'t require commenting or resolving. However, the backout may require commenting - click on "Add bugs" if so.',
-    notFoundBackouts: 'The following changesets have been detected as backouts, but the changesets or bugs backed out do not appear to be within this merge. Review this information, and manually comment in Bugzilla as necessary.',
-    merges: 'The following changesets have been detected to be merge changesets, not tied to any particular bug. Review these changesets - use the add bug button or resolve manually in Bugzilla to deal with any that are misdetected.',
-    others: 'These changesets do not appear to have a bug associated with them. Review these changesets, and comment in Bugzilla manually as necessary.'
-};
-
-
-Step.headings = {
-    fixes: 'Fixes',
-    foundBackouts: 'Pushes backed out',
-    notFoundBackouts: 'Backouts of things not in this merge',
-    merges: 'Merge Changesets',
-    others: 'Other Changesets'
-};
deleted file mode 100644
--- a/mcmerge/js/Summary.js
+++ /dev/null
@@ -1,149 +0,0 @@
-"use strict";
-
-var Summary = {
-  makeSummaryForData: function summary_makeSummaryForData(data) {
-    var html = '<tr><td>' + UI.linkifyBug(data.id) + '</td><td>';
-    if ('status' in data && data.status == 'RESOLVED')
-      html += 'Y';
-    else
-      html += 'N';
-    html += '</td><td>';
-    if ('status' in data && data.status == 'REOPENED')
-      html += 'Y';
-    else
-      html += 'N';
-    html += '</td><td>';
-    if ('target_milestone' in data)
-      html += data.target_milestone;
-    else
-      html += '&nbsp;';
-    html += '</td><td>';
-    if ('assigned_to' in data)
-      html += UI.htmlEncode(data.assigned_to.name);
-    else
-     html += '&nbsp;';
-    html += '</td><td>';
-    if ('comments' in data) {
-      var comment = data.comments[0].text;
-      comment = comment.replace(/\n/g, '<br>');
-      Config.hgRevFullRE.lastIndex = 0;
-      comment = comment.replace(Config.hgRevFullRE, function(str) {return UI.linkifyRevURL(str);});
-      html += comment;
-    } else
-      html += '&nbsp;';
-    html += '</tr>';
-    return html;
-  },
-
-
-  makeSummaryForStep: function summary_makeSummaryForStep(step) {
-    var html = '<h3>' + step.getHeading(false) + '</h3>';
-    var sent = step.getSentData();
-    if (sent.length == 0) {
-      html += '<p><em>No changes submitted.</em></p>';
-      return html;
-    }
-
-    html += '<br><table class="summaryTable"><tr class="thead"><td>Bug</td><td>Resolved?</td>';
-    html += '<td>Reopened?</td><td>Target Milestone</td><td>Assignee</td><td>Comment</td></tr>';
-    html += sent.map(function(data) {return this.makeSummaryForData(data);}, this).join('');
-    html += '</table>';
-    return html;
-  },
-
-
-  makeUnsubmittedHTML: function summary_makeUnsubmittedHTML(steps) {
-    var subhtml = '';
-    for (var i = 0; i < steps.length; i++) {
-       if (steps[i].canSubmit())
-         subhtml += '<li>'+steps[i].getHeading(false)+'</li>';
-    }
-
-    if (subhtml == '')
-      return subhtml;
-
-    var html = '<p><span class="subwarn">WARNING: </span>The following steps seem to have changes that could be sent to Bugzilla,';
-    html += ' but have not been submitted. You may wish to double-check them:</p><ul>' + subhtml + '</ul>';
-    return html;
-  },
-
-
-  makeSecBugHTML: function summary_makeSecBugHTML(steps) {
-    var sechtml = '';
-    for (var i = 0; i < steps.length; i++) {
-       if (steps[i].hasSecurityBugs()) {
-         sechtml += '<li>'+steps[i].getHeading(false) + '<br>';
-         var sb = steps[i].getSecurityBugs();
-         sechtml += '<table><tr><td>Changeset</td><td>Link</td><td>Bug</td></tr>';
-         for (var j = 0; j < sb.length; j++) {
-           sechtml += '<tr><td>' + sb[j].cset + '</td><td>' + UI.linkifyRevURL(sb[j].link);
-           sechtml += '</td><td>' + UI.linkifyBug(sb[j].bug) + '</td></tr>';
-         }
-         sechtml += '</table>';
-      }
-    }
-
-    if (sechtml == '')
-      return sechtml;
-
-    var html = '<p>The following steps had security bugs, which you will need to check';
-    html += ' and resolve/comment manually:</p><ul>' + sechtml + '</ul>';
-    return html;
-  },
-
-
-  makeButtonHTML: function summary_makeButtonHTML(prevLabel, nextLabel) {
-    var html = '<div class="grid-4">';
-    html += '  <button type="button" class="summaryPrevButton">' + prevLabel + '</button>';
-    html += '</div>';
-    html += '<div class="grid-4"></div>';
-    html += '<div class="grid-4 divRight">';
-    html += '  <button type="button" class="summaryNextButton">' + nextLabel + '</button>';
-    html += '</div>'
-    return html;
-  },
-
-
-  view: function summary_View(steps, onPrevious, onNext) {
-    // Hide any previous viewer output
-    UI.hide('viewerOutput');
-    UI.clearErrorMessage();
-    $('#viewerOutput').empty();
-    $('#viewerOutput').append(this.makeButtonHTML(onPrevious.label, onNext.label));
-
-    var subHTML = this.makeUnsubmittedHTML(steps);
-    if (subHTML != '')
-      $('#viewerOutput').append(subHTML + '<hr>');
-
-    var secHTML = this.makeSecBugHTML(steps);
-    if (secHTML != '')
-      $('#viewerOutput').append(secHTML + '<hr>');
-
-    $('#viewerOutput').append('<div class="ctr"><h3 class="summaryHeading">Summary of activity</h3></div>');
-
-    steps.forEach(function step_viewSummaryMaker(step){
-      $('#viewerOutput').append(this.makeSummaryForStep(step));
-    }, this);
-
-    $('#viewerOutput').append(this.makeButtonHTML(onPrevious.label, onNext.label));
-    if (onPrevious.fn) {
-      $('.summaryPrevButton').click(function Step_onPreviousClick(e) {
-        onPrevious.fn();
-      });
-    } else {
-      $('.summaryPrevButton').attr('disabled', true);
-    }
-
-    if (onNext.fn) {
-      $('.summaryNextButton').click(function Step_onNextClick(e) {
-        onNext.fn();
-      });
-    } else {
-      $('.summaryNextButton').attr('disabled', true);
-    }
-
-    UI.show('viewerOutput');
-    $('html')[0].scrollIntoView();
-  }
-}
-
deleted file mode 100644
--- a/mcmerge/js/UI.js
+++ /dev/null
@@ -1,401 +0,0 @@
-"use strict";
-
-var UI = {
-  modalID: null,
-  modalForm: null,
-  modalCancelAction: null,
-  modalSubmitAction: null,
-  modalCancelButton: null,
-
-
-  // Encode text for HTML insertion per OWASP guidelines
-  htmlEncode: function UI_makeHTMLencode(input) {
-    input = input.replace('&', '&amp;', 'g');
-    input = input.replace('<', '&lt;', 'g');
-    input = input.replace('>', '&gt;', 'g');
-    input = input.replace('"', '&quot;', 'g');
-    input = input.replace("'", '&#x27;', 'g');
-    input = input.replace('/', '&#x2f;', 'g');
-    return input;
-  },
-
-
-  hideAll: function UI_hideAll() {
-    var selector = '.hideAll';
-    $(selector).addClass('hiddenContent');
-  },
-
-
-  hide: function UI_hide(selector) {
-    selector = '#' + selector;
-    if (!$(selector).hasClass('hiddenContent'))
-      $(selector).addClass('hiddenContent');
-  },
-
-
-  show: function UI_show(selector) {
-    selector = '#' + selector;
-    if ($(selector).hasClass('hiddenContent'))
-      $(selector).removeClass('hiddenContent');
-  },
-
-
-  hideLoadingMessage: function UI_hideLoadingMessage(message) {
-    this.hide('loading');
-  },
-
-
-  showLoadingMessage: function UI_showLoadingMessage(message) {
-    this.hideAll();
-    $('#loading').text(message);
-    this.show('loading');
-  },
-
-
-  hideLoadingOverlay: function UI_hideLoadingOverlay() {
-    $('#loadingModal').toggle();
-    $('#opaque').toggle();
-  },
-
-
-  showLoadingOverlay: function UI_showLoadingOverlay() {
-    $('#opaque').toggle();
-    $('#loadingModal').toggle();
-  },
-
-
-  showInvalidEmailDialog: function UI_showInvalidEmailDialog() {
-    this.hideLoadingOverlay();
-    UI.showMessageModal('That didn\'t look like a valid email address!');
-  },
-
-
-  showInvalidBugDialog: function UI_showInvalidBugDialog() {
-    this.hideLoadingOverlay();
-    UI.showMessageModal('That didn\'t look like a valid bug number!');
-  },
-
-
-  showBugSubmitDialog: function UI_showBugSubmitDialog(sent, total) {
-    $('#submissionMessage').attr('data-sent', sent);
-    $('#submissionMessage').attr('data-max', total);
-    $('#submissionMessage').dialog('open');
-  },
-
-
-  clearErrorMessage: function UI_clearErrorMessage() {
-    this.hide('errors');
-    $('#errorText').text('');
-  },
-
-
-  showErrorMessage: function UI_showErrorMessage(message) {
-    this.hide('errors');
-    $('#errorText').text(message);
-    this.show('errors');
-    $('html')[0].scrollIntoView();
-  },
-
-
-  hideProgressModal: function UI_hideProgressModal() {
-    $('#progressModal').toggle();
-    $('#opaque').toggle();
-  },
-
-
-  updateProgressModal: function UI_updateProgressModal(percentage) {
-    percentage = Math.round(Number(percentage));
-    $('#progressBar').attr('value', percentage);
-    $('#progressText').text(percentage);
-  },
-
-
-  showProgressModal: function UI_showProgressModal(noReset) {
-    noReset = noReset || false;
-    if (!noReset) {
-      $('#progressBar').attr('value', '0');
-      $('#progressBar').attr('max', '100');
-      $('#progressText').text('0');
-    }
-    $('#opaque').toggle();
-    $('#progressModal').toggle();
-  },
-
-
-  onModalKey: function UI_onModalKey(e) {
-    if (e.metaKey || e.altKey || e.ctrlKey || e.which != 27)
-      return true;
-
-    e.preventDefault(); 
-    if (UI.modalForm)
-      $(UI.modalForm).unbind('submit', UI.onModalConfirm);
-    if (UI.cancelButton)
-      $(UI.cancelButton).unbind('click', UI.onModalCancel);
-    $(document).unbind('keydown', UI.onModalKey); 
-    UI.hideModalForm();
-    if (UI.modalCancelAction)
-      UI.modalCancelAction(); 
-  },
-
-
-  onModalCancel: function UI_onModalCancel(e) {
-    e.preventDefault();
-    $(document).bind('keydown', UI.onModalKey);
-    if (UI.modalForm)
-      $(UI.modalForm).unbind('submit', UI.onModalConfirm);
-    UI.hideModalForm();
-    if (UI.modalCancelAction)
-      UI.modalCancelAction(); 
-  },
-
-
-  onModalConfirm: function UI_onModalConfirm(e) {
-    e.preventDefault();
-    if (UI.cancelButton) {
-      $(UI.cancelButton).unbind('click', UI.onModalCancel);
-      $(document).unbind('keydown', UI.onModalKey); 
-    }
-    UI.hideModalForm();
-    if (UI.modalSubmitAction)
-      UI.modalSubmitAction();
-  },
-
-
-  hideModalForm: function UI_hideModalForm() {
-    $(UI.modalID).toggle();
-    $('#opaque').toggle();
-    UI.modalID = null;
-  },
-
-
-  showModalForm: function UI_showModalForm(id, formID, submitAction, cancelID, cancelAction) {
-    UI.modalID = '#' + id;
-    if (formID) {
-      UI.modalForm = '#' + formID;
-      if (submitAction)
-        UI.modalSubmitAction = submitAction;
-      $(UI.modalForm).one('submit', UI.onModalConfirm);
-    }
-    if (cancelID) {
-      UI.cancelButton = '#' + cancelID;
-      $(document).bind('keydown', UI.onModalKey);
-      if (cancelAction)
-        UI.modalCancelAction = cancelAction;
-      $(UI.cancelButton).one('click', UI.onModalCancel);
-    }
-    $('#opaque').toggle();
-    $(UI.modalID).toggle();
-  },
-
-
-  onExplanationSubmit: function UI_onExplanationSubmit(e, callback) {
-    var text = $('#explanation').val();
-    if (text != '' && text[text.length - 1] != '\n')
-      text = text + '\n';
-    var useForAll = $('#useForAll').prop('checked');
-    UI.showProgressModal(true);
-    callback(text, useForAll);
-  },
-
-
-  onExplanationCancel: function UI_onExplanationCancel(e, callback) {
-    UI.showProgressModal(true);
-    callback('', false);
-  },
-
-
-  acquireExplanation: function UI_acquireExplanation(callback, bug) {
-    $('#explanation').val('');
-    $('#useForAll').prop('checked', false);
-    $('#exTitle').text('Add explanation for backout of ' + bug);
-    UI.hideProgressModal();
-    UI.showModalForm('explanationModal', 'explanationForm', function(e) {UI.onExplanationSubmit(e, callback);},
-                     'exCancel', function(e) {UI.onExplanationCancel(e, callback);});
-    $('#explanation')[0].focus();
-  },
-
-
-  onCredentialsSubmit: function UI_onCredentialsSubmit(e) {
-    ViewerController.onCredentialsEntered($('#username').val(), $('#password').val());
-    $('#username').val('');
-    $('#password').val('');
-  },
-
-
-  onCredentialsCancel: function UI_onCredentialsCancel(e) {
-    $('#username').val('');
-    $('#password').val('');
-  },
-
-
-  showCredentialsForm: function UI_showCredentialsForm() {
-    $('#username').val('');
-    $('#password').val('');
-    UI.showModalForm('credentialsModal', 'credentialsForm', UI.onCredentialsSubmit,
-                     'crCancel', UI.onCredentialsCancel);
-    $('#username')[0].focus();
-  },
-
-
-  onAddBugSubmit: function UI_onAddBugSubmit(e) {
-    var index = $('#addBugForm').attr('data-index');
-    ViewerController.onAddBug(parseInt(index), $('#loadBug').val());
-  },
-
-
-  showBugLoadForm: function UI_showBugChangeForm(index) {
-    var cset = PushData.allPushes[index].cset;
-    $('#abTitle').text('Add bug to ' + cset);
-    $('#loadBug').val('');
-    $('#addBugForm').attr('data-index', index);
-    UI.showModalForm('addBugModal', 'addBugForm', UI.onAddBugSubmit, 'abCancel');
-    $('#loadBug')[0].focus();
-  },
-
-
-  onChangeBugSubmit: function UI_onChangeBugSubmit(e) {
-    var index = $('#changeBugForm').attr('data-index');
-    var bug = $('#changeBugForm').attr('data-bug');
-    ViewerController.onChangeBug(parseInt(index), bug, $('#changeBug')[0].value);
-  },
-
-
-  onChangeBugCancel: function UI_onChangeBugCancel(e) {
-    var cset = $('#changeBugForm').attr('data-cset');
-    var bug = $('#changeBugForm').attr('data-bug');
-    Viewer.addChangeButtonListener(cset, bug);
-  },
-
-
-  showBugChangeForm: function UI_showBugChangeForm(index, bug) {
-    var cset = PushData.allPushes[index].cset;
-    $('#cbTitle').text('Change bug ' + bug + ' for ' + cset);
-    $('#changeBug').val('');
-    $('#changeBugForm').attr('data-index', index);
-    $('#changeBugForm').attr('data-bug', bug);
-    $('#changeBugForm').attr('data-cset', cset);
-    UI.showModalForm('changeBugModal', 'changeBugForm', UI.onChangeBugSubmit,
-                     'cbCancel', UI.onChangeBugCancel);
-    $('#changeBug')[0].focus();
-  },
-
-
-  onMessageKey: function UI_onMessageKey(e) {
-    if (e.metaKey || e.altKey || e.ctrlKey || e.which != 27)
-      return true;
-
-    e.preventDefault(); 
-    $('#mmOK').click();
-  },
-
-
-  showMessageModal: function UI_showMessageModal(message) {
-    $('#mmText').text(message);
-
-    var onOK = function UI_showMessageModal_onOK() {
-      $('#messageModal').toggle();
-      $(document).unbind('keydown', UI.onMessageKey);
-      $('#opaque').toggle();
-    }
-
-    $('#mmOK').one('click', onOK);
-    $(document).bind('keydown', UI.onMessageKey);
-    $('#opaque').toggle();
-    $('#messageModal').toggle();
-    $('#mmOK')[0].focus();
-  },
-
-
-  showForm: function UI_showForm(listener) {
-    this.hideAll();
-
-    // Hook up click listener
-    if (typeof listener == 'function')
-      $('#csetForm').one('submit', listener);
-
-    this.show('getCset');
-    $('#changeset').focus();
-  },
-
-
-  showFormWithError: function UI_ShowFormWithError(listener, errorText) {
-    // Call showForm first, as it will call hideAll
-    this.showForm(listener);
-    this.showErrorMessage(errorText);
-  },
-
-
-  linkifyChangeset: function UI_linkifyChangeset(cset) {
-    var link = Config.hgRevURL;
-    if (cset.indexOf(link) != -1)
-      cset = cset.substring(link.length);
-    link += cset;
-    return '<a href="' + link + '" target="_blank">' + cset + '</a>';
-  },
-
-
-  linkifyRevURL: function UI_linkifyChangeset(revURL) {
-    var cset = revURL;
-    var link = Config.hgRevURL;
-    if (cset.indexOf(link) != -1)
-      cset = cset.substring(link.length);
-    link += cset;
-    return '<a href="' + link + '" target="_blank">' + revURL + '</a>';
-  },
-
-
-  linkifyBug: function UI_linkifyBug(bug) {
-    return '<a href="' + Config.showBugURL + bug + '" target="_blank">' + bug + '</a>';
-  },
-
-
-  linkifyDescription: function UI_linkifyDescription(desc) {
-    Config.csetIDRE.lastIndex = 0;
-    Config.bugNumRE.lastIndex = 0;
-    desc = desc.replace(Config.csetIDRE, this.linkifyChangeset);
-    desc = desc.replace(Config.bugNumRE, this.linkifyBug);
-    return desc;
-  },
-
-
-  buildMergeVerification: function UI_displayMergeVerification(sourceRepo) {
-    var html = '';
-    if (sourceRepo) {
-      html += (PushData.allPushes.length > 150) ? 'Übermerge' : 'Merge';
-      html += ' from <a href="' + Config.hgBaseURL + Config.treeInfo[sourceRepo].repo + '" target="_blank">' + sourceRepo.toLowerCase() + '</a> ';
-      html += 'to <a href="' + Config.hgURL + '" target="_blank">mozilla-central</a>';
-    } else {
-      html += 'Push to <a href="' + Config.hgURL + '" target="_blank">' + Config.treeName + '</a>';
-    }
-    return html;
-  },
-
-
-  displayDetail: function UI_displayDetail() {
-    var tipCset = PushData.allPushes[PushData.allPushes.length - 1].cset;
-    var numPushes = PushData.allPushes.length;
-    var pushesParsed = 0;
-    var pushTypes = ['fixes', 'backedOut', 'foundBackouts', 'notFoundBackouts', 'merges', 'others'];
-    pushTypes.forEach(function(arr) {pushesParsed += PushData[arr].length});
-
-    this.hide('detail');
-    var html = '';
-
-
-    html += this.buildMergeVerification(this.sourceRepo);
-    html += ' (view <a href="' + Config.hgPushlogURL + tipCset + '" target="_blank">pushlog</a>).';
-    $('#detail').html(html);
-    this.show('detail');
-    this.displayVerificationWarning(numPushes, pushesParsed);
-  },
-
-
-  displayVerificationWarning: function UI_displayVerificationWarning(rightLength, actualLength) {
-    if (rightLength == actualLength)
-      return;
-
-    var errorText = 'Warning: Pushes length verification failed. (' + rightLength + ',' + actualLength + ')';
-    errorText += 'Please ping :graememcc with this cset!';
-    this.showErrorMessage(errorText);
-  }
-};
deleted file mode 100644
--- a/mcmerge/js/Utils.js
+++ /dev/null
@@ -1,251 +0,0 @@
-// Add the various Array extensions used, where they are not natively
-// supported. Code courtesy of https://developer.mozilla.org
-
-if (!Array.prototype.filter) {
-  Array.prototype.filter = function(fun /*, thisp */) {
-    "use strict";
-
-    if (this == null)
-      throw new TypeError();
-
-    var t = Object(this);
-    var len = t.length >>> 0;
-    if (typeof fun != "function")
-      throw new TypeError;
-
-    var res = [];
-    var thisp = arguments[1];
-    for (var i = 0; i < len; i++) {
-      if (i in t) {
-        var val = t[i];
-        if (fun.call(thisp, val, i, t))
-          res.push(val);
-      }
-    }
-
-    return res;
-  };
-}
-
-if (!Array.prototype.forEach) {
-  Array.prototype.forEach = function(callback, thisArg) {
-    var T, k;
-
-    if (this == null) {
-      throw new TypeError(" this is null or not defined");
-    }
-
-    // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
-    var O = Object(this);
-
-    // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
-    // 3. Let len be ToUint32(lenValue).
-    var len = O.length >>> 0; // Hack to convert O.length to a UInt32
-
-    // 4. If IsCallable(callback) is false, throw a TypeError exception.
-    // See: http://es5.github.com/#x9.11
-    if ({}.toString.call(callback) != "[object Function]") {
-      throw new TypeError(callback + " is not a function");
-    }
-
-    // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
-    if (thisArg) {
-      T = thisArg;
-    }
-
-    // 6. Let k be 0
-    k = 0;
-
-    // 7. Repeat, while k < len
-    while(k < len) {
-
-      var kValue;
-
-      // a. Let Pk be ToString(k).
-      //   This is implicit for LHS operands of the in operator
-      // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
-      //   This step can be combined with c
-      // c. If kPresent is true, then
-      if (k in O) {
-        // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
-        kValue = O[k];
-
-        // ii. Call the Call internal method of callback with T as the this value and
-        // argument list containing kValue, k, and O.
-        callback.call(T, kValue, k, O);
-      }
-      // d. Increase k by 1.
-      k++;
-    }
-    // 8. return undefined
-  };
-}
-
-if (!Array.prototype.map) {
-  Array.prototype.map = function(callback, thisArg) {
-
-    var T, A, k;
-
-    if (this == null) {
-      throw new TypeError(" this is null or not defined");
-    }
-
-    // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
-    var O = Object(this);
-
-    // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
-    // 3. Let len be ToUint32(lenValue).
-    var len = O.length >>> 0;
-
-    // 4. If IsCallable(callback) is false, throw a TypeError exception.
-    // See: http://es5.github.com/#x9.11
-    if ({}.toString.call(callback) != "[object Function]") {
-      throw new TypeError(callback + " is not a function");
-    }
-
-    // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
-    if (thisArg) {
-      T = thisArg;
-    }
-
-    // 6. Let A be a new array created as if by the expression new Array(len) where Array is
-    // the standard built-in constructor with that name and len is the value of len.
-    A = new Array(len);
-
-    // 7. Let k be 0
-    k = 0;
-
-    // 8. Repeat, while k < len
-    while(k < len) {
-
-      var kValue, mappedValue;
-
-      // a. Let Pk be ToString(k).
-      //   This is implicit for LHS operands of the in operator
-      // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
-      //   This step can be combined with c
-      // c. If kPresent is true, then
-      if (k in O) {
-
-        // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
-        kValue = O[k];
-
-        // ii. Let mappedValue be the result of calling the Call internal method of callback
-        // with T as the this value and argument list containing kValue, k, and O.
-        mappedValue = callback.call(T, kValue, k, O);
-
-        // iii. Call the DefineOwnProperty internal method of A with arguments
-        // Pk, Property Descriptor {Value: mappedValue, Writable: true, Enumerable: true, Configurable: true},
-        // and false.
-
-        // In browsers that support Object.defineProperty, use the following:
-        // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
-
-        // For best browser support, use the following:
-        A[k] = mappedValue;
-      }
-      // d. Increase k by 1.
-      k++;
-    }
-
-    // 9. return A
-    return A;
-  };
-}
-
-if (!String.prototype.trim) {
-  String.prototype.trim = function() {
-    return this.replace(/^\s+|\s+$/g, '');
-  };
-}
-
-if (!Array.prototype.indexOf) {
-    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
-        "use strict";
-        if (this == null) {
-            throw new TypeError();
-        }
-        var t = Object(this);
-        var len = t.length >>> 0;
-        if (len === 0) {
-            return -1;
-        }
-        var n = 0;
-        if (arguments.length > 0) {
-            n = Number(arguments[1]);
-            if (n != n) { // shortcut for verifying if it's NaN
-                n = 0;
-            } else if (n != 0 && n != Infinity && n != -Infinity) {
-                n = (n > 0 || -1) * Math.floor(Math.abs(n));
-            }
-        }
-        if (n >= len) {
-            return -1;
-        }
-        var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
-        for (; k < len; k++) {
-            if (k in t && t[k] === searchElement) {
-                return k;
-            }
-        }
-        return -1;
-    }
-}
-
-if (!Object.keys) {
-  Object.keys = (function () {
-    var hasOwnProperty = Object.prototype.hasOwnProperty,
-        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
-        dontEnums = [
-          'toString',
-          'toLocaleString',
-          'valueOf',
-          'hasOwnProperty',
-          'isPrototypeOf',
-          'propertyIsEnumerable',
-          'constructor'
-        ],
-        dontEnumsLength = dontEnums.length
-
-    return function (obj) {
-      if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object')
-
-      var result = []
-
-      for (var prop in obj) {
-        if (hasOwnProperty.call(obj, prop)) result.push(prop)
-      }
-
-      if (hasDontEnumBug) {
-        for (var i=0; i < dontEnumsLength; i++) {
-          if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i])
-        }
-      }
-      return result
-    }
-  })()
-};
-
-if (!Date.prototype.toISOString ) {
-  (function() {
-    function pad(number) {
-      var r = String(number);
-      if (r.length === 1) {
-        r = '0' + r;
-      }
-      return r;
-    }
-
-    Date.prototype.toISOString = function() {
-      return this.getUTCFullYear()
-        + '-' + pad( this.getUTCMonth() + 1 )
-        + '-' + pad( this.getUTCDate() )
-        + 'T' + pad( this.getUTCHours() )
-        + ':' + pad( this.getUTCMinutes() )
-        + ':' + pad( this.getUTCSeconds() )
-        + '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 )
-        + 'Z';
-    };
-
-  }());
-}
deleted file mode 100644
--- a/mcmerge/js/Viewer.js
+++ /dev/null
@@ -1,686 +0,0 @@
-"use strict";
-
-var Viewer = {
-  init: function viewer_init() {
-    var listener = this.listener;
-    function bindListener(that, listeners) {
-      return function (e) {
-        listener.call(that, listeners, e);
-      };
-    }
-
-    var indexOnly = ['index'];
-    var indexBug = ['index', 'bug'];
-
-    var clickListeners = {
-      'addBug'      : this.decorateWithRequired(this.onAddButtonClick, indexOnly, 'Add'),
-      'changeButton': this.decorateWithRequired(this.onChangeButtonClick, indexBug, 'Change'),
-      'removeButton': this.decorateWithRequired(this.onRemoveButtonClick, indexBug, 'Remove'),
-      'commentCheck': this.decorateWithRequired(this.onCommentCheckClick, indexBug, 'Comment'),
-      'resolveCheck': this.decorateWithRequired(this.onResolveCheckClick, indexBug, 'Resolve'),
-      'reopenCheck' : this.decorateWithRequired(this.onReopenCheckClick, indexBug, 'Reopen'),
-      'viewhide'    : this.decorateWithRequired(this.onViewHideClick, indexBug, 'View/Hide'),
-      'fileviewhide': this.decorateWithRequired(this.onFileViewHideClick, indexOnly, 'View/Hide files'),
-      'expandButton': this.onExpandButtonClick,
-      'submitButton': this.onSubmitButtonClick,
-      'prevButton'  : this.onPreviousButtonClick,
-      'nextButton'  : this.onNextButtonClick
-    };
-
-    var inputListeners = {
-      'comment': this.decorateWithRequired(this.onCommentInput, indexBug, 'Comment text'),
-      'whiteboardTA': this.decorateWithRequired(this.onWhiteboardInput, indexBug, 'Whiteboard')
-    };
-
-    var changeListeners = {
-      'milestone': this.decorateWithRequired(this.onMilestoneChange, indexBug, 'Milestone'),
-      'testsuite': this.decorateWithRequired(this.onTestsuiteChange, indexBug, 'Testsuite')
-    };
-
-    var self = this;
-    $('#viewerOutput').click(bindListener(self, clickListeners));
-    $('#viewerOutput').on('input', bindListener(self, inputListeners));
-    $('#viewerOutput').on('change', bindListener(self, changeListeners));
-  },
-
-
-  listener: function viewer_listener(listeners, e) {
-    var className = e.target.className.split(' ')[0];
-    if (!(className in listeners))
-      return;
-
-    listeners[className].call(this, e.target);
-  },
-
-
-  decorateWithRequired: function viewer_decorateWithRequired(fn, required, which) {
-    return function (target) {
-      var args = [];
-      for (var i = 0; i < required.length; i++) {
-        var attribute = 'data-' + required[i];
-        if (!target.hasAttribute(attribute)) {
-          UI.showErrorMessage(which + ' had event without data!');
-          return;
-        }
-        args.push(target.getAttribute(attribute));
-      }
-      args.push(target);
-      fn.apply(this, args);
-    };
-  },
-
-  // Buttons
-  onPreviousButtonClick: function viewer_onPreviousButtonClick() {
-    if (this.onPreviousFn)
-      this.onPreviousFn();
-  },
-
-
-  onNextButtonClick: function viewer_onNextButtonClick() {
-    if (this.onNextFn)
-      this.onNextFn();
-  },
-
-
-  onAddButtonClick: function viewer_onAddButtonClick(index, target) {
-    UI.showBugLoadForm(index);
-  },
-
-
-  onChangeButtonClick: function viewer_onChangeButtonClick(index, bug, target) {
-    UI.showBugChangeForm(index, bug);
-  },
-
-
-  onRemoveButtonClick: function viewer_onRemoveButtonClick(index, bug, target) {
-    ViewerController.removeBug(index, bug);
-  },
-
-
-  onExpandButtonClick: function viewer_onExpandButtonClick(target) {
-    var shouldExpand = $('#expandButton').text() === 'Expand all comments';
-    $('.commentDiv').toggle(shouldExpand);
-    var expandText = shouldExpand ? 'Hide all comments' : 'Expand all comments';
-    $('#expandButton').text(expandText);
-    var individualText = shouldExpand ? 'Hide comment' : 'View comment';
-    $('.viewhide').text(individualText);
-  },
-
-
-  onSubmitButtonClick: function viewer_onSubmitButtonClick(target) {
-    this.step.onSubmit();
-  },
-
-
-  // Spans
-  onViewHideClick: function viewer_onViewHideClick(index, bug, target) {
-    var cset = PushData.allPushes[index].cset;
-    var currentText = target.textContent;
-    var expandThis = currentText == 'View comment';
-    $('#' + this.getCommentID(cset, bug)).toggle(expandThis);
-    target.textContent = expandThis ? 'Hide comment' : 'View comment';
-    
-    // Update 'expand all' button text
-    var shouldExpand = false;
-    if (expandThis) {
-      var divs = $('.commentDiv').get();
-      for (var i = 0, l = divs.length; i < l; i++) {
-        var style = divs[i].style.display.toLowerCase();
-        if (style === 'none' || style === '')
-          shouldExpand = true;
-      }
-    } else {
-      // Shortcut if we've just minimised a comment
-      shouldExpand = true;
-    }
-
-    var expandText = shouldExpand ? 'Expand all comments' : 'Hide all comments';
-    $('#expandButton').text(expandText);
-  },
-
-
-  onFileViewHideClick: function viewer_onFileViewHideClick(cset, target) {
-    var shouldExpand = target.textContent == 'View files';
-    $('#' + this.getFilesID(cset)).toggle(shouldExpand);
-
-    // Flip the text appropriately
-    var classes = target.className.split(' ');
-    var classToChange = '';
-    for (var i = 0; i < classes.length; i++) {
-      if (classes[i].indexOf('Files') != -1)
-        classToChange = classes[i];
-    }
-    var newText = shouldExpand ? 'Hide files' : 'View files';
-    $('.' + classToChange).text(newText);
-  },
-
-
-  // Text inputs
-  onCommentInput: function viewer_onCommentInput(index, bug, target) {
-    ViewerController.onCommentInput(index, bug, target.value);
-  },
-
-
-  onWhiteboardInput: function viewer_onWhiteboardInput(index, bug, target) {
-    $('.' + bug + 'whiteboard').val(target.value); 
-    ViewerController.onWhiteboardInput(index, bug, target.value);
-  },
-
-
-  // Checkboxes
-  onResolveCheckClick: function viewer_onResolveCheckClick(index, bug, target) {
-    // Update all other instances of this bug
-    $('.'+bug+'resolvecheck').attr('checked', target.checked);
-
-    // If we've turned it off, also turn off milestone selection
-    // (we don't support setting the milestone without setting the
-    // resolution).
-    $('.'+bug+'Milestone').attr('disabled', !target.checked);
-
-    ViewerController.onResolveCheckClick(bug, target.checked);
-  },
-
-
-  onReopenCheckClick: function viewer_onReopenCheckClick(index, bug, target) {
-    // Update all other instances of this bug
-    $('.'+bug+'reopencheck').attr('checked', target.checked);
-
-    // If we've turned it on, also turn on commenting - I don't think
-    // you would ever backout a bug without an explanation!
-    this.unsetComments(bug, target.checked);
-    ViewerController.onReopenCheckClick(bug, target.checked);
-  },
-
-
-  onCommentCheckClick: function viewer_onCommentCheckClick(index, bug, target) {
-    ViewerController.onCommentCheckClick(index, bug, target.checked);
-
-    // Comments and reopening are dependent
-    if (ViewerController.getCurrentStep().canReopen(bug)) {
-      this.unsetComments(bug, target.checked);
-      var elems = $('.' + bug + 'reopencheck');
-      if (elems.length > 0 && elems.attr('checked') != target.checked)
-        elems[0].click();
-    }
-  },
-
-
-  unsetComments: function viewer_unsetComments(bug, checked) {
-    var elems = $('.' + bug + 'commentcheck');
-    var l = elems.length;
-    for (var i = 0; i < l; i++) {
-      var elem = elems[i];
-      if (elem.getAttribute('checked') != checked) {
-        var index = elem.getAttribute('data-index');
-        ViewerController.onCommentCheckClick(index, bug, checked);
-      }
-    }
-    elems.attr('checked', checked);
-  },
-
-
-  // Selects
-  onMilestoneChange: function viewer_onMilestoneChange(index, bug, target) {
-    // Update all other instances of this bug
-    $('.'+bug+'Milestone').val(target.value);
-    ViewerController.onMilestoneChange(bug, target.value);
-  },
-
-
-  onTestsuiteChange: function viewer_onTestsuiteChange(index, bug, target) {
-    // Update all other instances of this bug
-    $('.'+bug+'Testsuite').val(target.value);
-    ViewerController.onTestsuiteChange(bug, target.value);
-  },
-
-
-  addBug: function viewer_attachBug(index, bugID) {
-    var cset = PushData.allPushes[index].cset;
-
-    var bugHTML = this.makeBugHTML(index, bugID);
-    $('#' + this.getBugDivID(cset)).prepend(bugHTML);
-
-    this.updateSubmitButton();
-  },
-
-
-  // Assumes the bug has already been removed from attachedBugs[cset]
-  removeBug: function viewer_removeBug(index, id) {
-    var cset = PushData.allPushes[index].cset;
-    $('#' + this.getBugCsetID(cset, id)).remove();
-    this.updateSubmitButton();
-  },
-
-
-  getAddBugIDForCset: function viewer_getAddBugIDForPush(index) {
-    return 'addBug' + index;
-  },
-
-
-  getBugCsetID: function viewer_getBugCsetID(cset, id) {
-    return cset + id;
-  },
-
-
-  getMilestonesID: function viewer_getMilestones(cset, id) {
-    return cset + id + 'Milestones';
-  },
-
-
-  getTestsuiteID: function viewer_getTestsuiteID(cset, id) {
-    return cset + id + 'Testsuite';
-  },
-
-
-  getViewHideID: function viewer_getViewHideID(cset, id) {
-    return cset + id + 'ViewHide';
-  },
-
-
-  getFilesID: function viewer_getFilesID(cset) {
-    return cset + 'Files';
-  },
-
-
-  getCommentCheckID: function viewer_getCommentCheckID(cset, id) {
-    return cset + id + 'CommentCheck';
-  },
-
-
-  getResolveCheckID: function viewer_getResolveCheckID(cset, id) {
-    return cset + id + 'ResolveCheck';
-  },
-
-
-  getReopenCheckID: function viewer_getReopenCheckID(cset, id) {
-    return cset + id + 'ReopenCheck';
-  },
-
-
-  getRemoveButtonID: function viewer_getRemoveButtonID(cset, id) {
-    return cset + id + 'Remove';
-  },
-
-
-  getChangeButtonID: function viewer_getChangeButtonID(cset, id) {
-    return cset + id + 'Change';
-  },
-
-
-  getCommentID: function viewer_getCommentID(cset, id) {
-    return cset + id + 'Comment';
-  },
-
-
-  getCommentTextAreaID: function viewer_getCommentTextAreaID(cset, id) {
-    return cset + id + 'CommentText';
-  },
-
-
-  getWhiteboardID: function viewer_getWhiteboardID(cset, id) {
-    return cset + id + 'Whiteboard';
-  },
-
-
-  getBugDivID: function viewer_getBugDivID(cset) {
-    return cset + 'Bugs';
-  },
-
-
-  makeDataHTML: function viewer_makeDataHTML(index, bug) {
-    bug = bug || null;
-    var html = 'data-index="' + index + '" ';
-    if (bug)
-      html += 'data-bug="' + bug + '" ';
-    return html;
-  },
-
-
-  makeMilestoneSelectHTML: function viewer_makeMilestoneSelectHTML(cset, index, id) {
-    var html = '<select id="';
-    html += this.getMilestonesID(cset, id);
-    html += '" class="milestone ' + id + 'Milestone"';
-    html += ' ' + this.makeDataHTML(index, id);
-    if (!this.step.canResolve(id) || !this.step.shouldResolve(id) || !this.step.canSetMilestone(id))
-      html += ' disabled="true"';
-    html += '>';
-    var product = BugData.bugs[id].product;
-    var milestones = ConfigurationData.milestones[product].values;
-    var defaultMilestone = this.step.getMilestone(id);
-    for (var i = 0; i < milestones.length; i++) {
-      html += '<option value="' + milestones[i] + '"';
-      if (milestones[i] == defaultMilestone)
-        html += ' selected';
-      html += '>' + milestones[i] + '</option>';
-    }
-    html += '</select>';
-    return html;
-  },
-
-
-  makeTestsuiteHTML: function viewer_makeTestsuiteHTML(cset, index, id) {
-    var html = '<select id="';
-    html += this.getTestsuiteID(cset, id);
-    html += '" class="testsuite ' + id + 'Testsuite"';
-    html += ' ' + this.makeDataHTML(index, id);
-    html += '>';
-    var statuses = [' ', '?', '+', '-'];
-    var defaultStatus = this.step.getTestsuite(id);
-    for (var i = 0; i < statuses.length; i++) {
-      html += '<option value="' + statuses[i] + '"';
-      if (statuses[i] == defaultStatus)
-        html += ' selected';
-      html += '>' + statuses[i] + '</option>';
-    }
-    html += '</select>';
-    return html;
-  },
-
-
-  makeRemoveButtonHTML: function viewer_makeRemoveButtonHTML(cset, index, id) {
-     var html = '<button class="removeButton" id="' + this.getRemoveButtonID(cset, id) + '" ';
-     html += this.makeDataHTML(index, id);
-     html += ' type="button">Remove</button>';
-     return html;
-  },
-
-
-  makeChangeButtonHTML: function viewer_makeChangeButtonHTML(cset, index, bug) {
-     var html = '<button class="changeButton" id="' + this.getChangeButtonID(cset, bug) + '" ';
-     html += this.makeDataHTML(index, bug);
-     html += ' type="button">Change</button>';
-     return html;
-  },
-
-
-  makeCheckboxHTML: function viewer_makeCheckboxHTML(cset, index, id, type) {
-    var upperType = type.charAt(0).toUpperCase() + type.slice(1);
-    var html = '<input type="checkbox" class="' + type + 'Check';
-    html += ' ' + id + type + 'check" value="' + type + '"';
-    var canProp = "can" + upperType;
-    var shouldProp = "should" + upperType;
-    var idFn = 'get' + upperType + 'CheckID';
-    html += ' name="' + this[idFn](cset,id) + '"';
-    html += ' id="' + this[idFn](cset, id) + '" ';
-    html += this.makeDataHTML(index, id);
-    if (this.step.isAttached(index, id) && this.step.getProp(index, id, shouldProp))
-      html  += ' checked="checked"';
-    if (!this.step.isAttached(index, id) || !this.step.getProp(index, id, canProp)) {
-      html  += ' disabled="disabled"';
-    }
-    html += ' />';
-    return html;
-  },
-
-
-  makeCommentHTML: function viewer_makeCommentHTML(cset, index, id) {
-    var html = 'Comment: ';
-    html += '<textarea class="comment" rows="3" cols="60" id="' + this.getCommentTextAreaID(cset, id);
-    html += '" ' + this.makeDataHTML(index, id);
-    if (!this.step.canComment(index, id))
-      html += ' disabled="true"';
-    html += '>';
-    html += this.step.getComment(index, id);
-    html += '</textarea>';
-    return html;
-  },
-
-
-  makeWhiteboardHTML: function viewer_makeWhiteBoardHTML(cset, index, id) {
-    var bug = BugData.bugs[id];
-    var html = '<textarea class="whiteboardTA ' + id + 'whiteboard" rows="4" id="' + this.getWhiteboardID(cset, id);
-    html += '" ' + this.makeDataHTML(index, id) + '>';
-    if (bug.whiteboard)
-      html += bug.whiteboard.replace(/]/g, ']\n');
-    html += '</textarea>';
-    return html;
-  },
-
-
-  makeBugHTML: function viewer_makeBugHTML(index, id) {
-    var html = '';
-
-    var bug = BugData.bugs[id];
-    // Need to use the cset rather than index for unique IDs
-    // otherwise we could have eg index 8 bug 765432 and index 87 bug 65432 generating non-unique IDs
-    var cset = PushData.allPushes[index].cset;
-
-    html += '    <div class="bug'
-    if (bug && (bug.status == 'RESOLVED' || bug.status == 'VERIFIED'))
-      html += ' resolved';
-    html += '" id="' + this.getBugCsetID(cset, id) + '">';
-    html += '      <div class="grid-3">Bug ' + UI.linkifyBug(id) + '</div>';
-    html += '      <div class="grid-3">';
-    if (bug)
-      html += bug.status + " " + bug.resolution;
-    html += '      </div>';
-    html += '      <div class="grid-3">';
-    if (bug)
-      html += this.makeMilestoneSelectHTML(cset, index, id);
-    html += '      </div>';
-    html += '      <div class="grid-3 divRight">';
-    html += this.makeRemoveButtonHTML(cset, index, id);
-    html += this.makeChangeButtonHTML(cset, index, id);
-    html += '</div>';
-    html += '       <div class="grid-12">';
-    if (bug)
-      html += UI.linkifyDescription(bug.summary);
-    else
-      html += "<em>Unable to load bug " + id + " - security bug?</em>";
-    html += '</div>'
-    if (bug) {
-      html += '       <div class="grid-6 whiteboard">Whiteboard:';
-      html += this.makeWhiteboardHTML(cset, index, id);
-      html += '       </div>';
-    } else
-      html += '<div class="grid-6"></div>';
-    html += '<div class="grid-6 afterWhiteboard">';
-    if (bug && bug.leaveOpen)
-      html += ' <span class="afterWhiteboard leaveOpen">LEAVE OPEN</span><br>';
-    else
-      html += '<br>';
-    html += '<span class="afterWhiteboard">';
-    html += 'Comment: ';
-    html += this.makeCheckboxHTML(cset, index, id, 'comment');
-    html += ' Resolve: ';
-    html += this.makeCheckboxHTML(cset, index, id, 'resolve');
-    html += '</span>';
-    if (this.step.canReopen(id)) {
-      html += '<br><span class="afterWhiteboard">Reopen: ';
-      html += this.makeCheckboxHTML(cset, index, id, 'reopen');
-      html += '</span>';
-    } else
-      html += '<br>';
-    if (bug && bug.canSetTestsuite) {
-      html += '<span class="afterWhiteboard">In-testsuite: ';
-      html += this.makeTestsuiteHTML(cset, index, id);
-      html += '</span><br>';
-    } else
-      html += '<br>';
-    html += '<br>';
-    html += '<span class="afterWhiteboard">';
-    html += '<span class="viewhide" id="' + this.getViewHideID(cset, id) + '" ';
-    html += this.makeDataHTML(index, id) + '>View comment</span></span></div>';
-    html += '<div class="grid-12 commentDiv" id ="' + this.getCommentID(cset, id) + '">';
-    html += this.makeCommentHTML(cset, index, id);
-    html += '</div>';
-    html += '</div>';
-
-    return html;
-  },
-
-
-  makeBugDivHTML: function viewer_makeBugDivHTML(index) {
-    var html = '  <div id="' + this.getBugDivID(index) + '">';
-    html += '    </div>';
-    return html;
-  },
-
-
-
-  makeHTMLForChangeset: function viewer_makeHTMLForChangeset(index, classToAdd) {
-    var html = "";
-    var cset = PushData.allPushes[index].cset;
-    var desc = PushData.allPushes[index].desc;
-    var author = PushData.allPushes[index].author;
-    var files = PushData.allPushes[index].files;
-    html += '<div class="changeset';
-    if (classToAdd != '')
-      html += ' ' + classToAdd;
-    html += '">';
-    html += '  <div class="csetHead">';
-    html += '    <div class="csetTitle';
-    if (classToAdd != '')
-      html += ' ' + classToAdd;
-    html += '">';
-    html += '      <div class="grid-12">Changeset: '+ UI.linkifyChangeset(cset) + '</div>';
-    html += '    </div>';
-    html += '      <div class="grid-12">'+ author + '</div>';
-    html += '    <div class="grid-two-thirds">' + UI.linkifyDescription(desc);
-    html += '    </div>';
-    html += '    <div class="grid-one-third divRight">';
-    html += '      <button class="addBug" ' + this.makeDataHTML(index);
-    html += ' id="' + this.getAddBugIDForCset(index) + '" type="button">Add Bug</button>';
-    html += '    </div>';
-    html += '    <div class="grid-12"><span class="fileviewhide ' + cset + 'Files" ';
-    html += this.makeDataHTML(cset) + '>View files</span></div>';
-    html += '  </div>';
-    html += '  <div class="files hiddenContent" id="' + this.getFilesID(cset) + '">';
-    for (var i = 0; i < files.length; i++)
-      html += UI.htmlEncode(files[i]) + '<br />';
-    html += '    <span class="fileviewhide ' + cset + 'Files" ';
-    html += this.makeDataHTML(cset) + '>Hide</span>';
-    html += '    </div>';
-
-    return html;
-  },
-
-
-  makeBackoutBannerHTML: function viewer_makeBackoutBannerHTML() {
-    var html = '<div class="backoutbanner ctr" id="';
-    html += '">BACKED OUT BY</div>';
-   return html;
-  },
-
-
-  makeButtonHTML: function viewer_makeButtonHTML(prevLabel, nextLabel) {
-    var html = '<div class="grid-4">';
-    html += '  <button type="button" class="prevButton">' + prevLabel + '</button>';
-    html += '</div>';
-    html += '<div class="grid-4"></div>';
-    html += '<div class="grid-4 divRight">';
-    html += '  <button type="button" class="nextButton">' + nextLabel + '</button>';
-    html += '</div>'
-    return html;
-  },
-
-
-  makeExpandHTML: function viewer_makeExpandHTML() {
-    var html = '<div class="grid-12 divRight" id="expand">';
-    html += '  <button type="button" class="expandButton" id="expandButton">Expand all comments</button>';
-    html += '</div>';
-    return html;
-  },
-
-
-  makeSubmitHTML: function viewer_makeSubmitHTML() {
-    var html = '<div class="grid-12 divRight" class="submit">';
-    html += '  <button type="button" class="submitButton">Submit the changes</button>';
-    html += '</div>';
-    return html;
-  },
-
-
-  makeHeadlineHTML: function viewer_makeHeadlineHTML(headline) {
-    var html = '<div class="grid-12" id="headline">';
-    html += '<h3>' + headline + '</h3>';
-    html += '</div>';
-    return html;
-  },
-
-
-  makeHelpHTML: function viewer_buildHelp(helpText) {
-    var html = '<p class="grid-12" id="helpText">';
-    html += helpText;
-    html += '</p>';
-    return html;
-  },
-
-
-  updateHelpText: function viewer_updateHelpText() {
-    $('#helpText').replaceWith(this.makeHelpHTML(this.step.getHelpText()));
-  },
-
-
-  updateSubmitButton: function viewer_updateSubmitButton() {
-    $('.submitButton').attr('disabled', !(this.step.canSubmit()));
-  },
-
-
-  addChangeset: function viewer_addChangeset(index, isLast, classToAdd) {
-    classToAdd = classToAdd || '';
-    if (isLast)
-      classToAdd += ' last';
-    // build HTML for changeset part
-    var pushHTML = this.makeHTMLForChangeset(index, classToAdd);
-    pushHTML += this.makeBugDivHTML(PushData.allPushes[index].cset);
-    // build html for bugs
-    var attachedBugs = this.step.getAttachedBugs(index);
-    if (attachedBugs.length == 0)
-      return pushHTML +' </div>';
-
-    pushHTML += attachedBugs.map(function viewer_addChangsetBugHTMLMaker(j) {return this.makeBugHTML(index, j);},this).join('');
-    pushHTML += '</div>';
-    return pushHTML;
-  },
-
-
-  view: function view_View(step, onPrevious, onNext) {
-    // Hide any previous viewer output
-    UI.hide('viewerOutput');
-    UI.clearErrorMessage();
-    $('#viewerOutput').empty();
-
-    $('#viewerOutput').append(this.makeHeadlineHTML(step.getHeading()));
-    $('#viewerOutput').append(this.makeHelpHTML(step.getHelpText()));
-    $('#viewerOutput').append(this.makeExpandHTML());
-    $('#viewerOutput').append(this.makeSubmitHTML());
-    $('#viewerOutput').append(this.makeButtonHTML(onPrevious.label, onNext.label));
-
-    this.step = step;
-    var isBackedOut = step.hasBackouts;
-    var pushes = PushData[step.getName()];
-    var len = pushes.length;
-
-    if (!isBackedOut) {
-      var html = pushes.map(function viewer_ViewChangesetMaker(i, ind, arr) {return this.addChangeset(i, ind == arr.length - 1);}, this).join('');
-      $('#viewerOutput').append(html);
-    } else {
-      var html = pushes.map(function viewer_ViewChangesetMaker2(i, ind, arr) {
-        var h = PushData.allPushes[i].affected.map(function viewer_ViewBackoutMaker(j) {return this.addChangeset(j, false, 'backedout');}, this).join('');
-        return h + this.makeBackoutBannerHTML() + this.addChangeset(i, ind == arr.length - 1, 'backout');
-      }, this).join('');
-      $('#viewerOutput').append(html);
-    }
-
-    $('#viewerOutput').append(this.makeSubmitHTML());
-    $('#viewerOutput').append(this.makeButtonHTML(onPrevious.label, onNext.label));
-    this.onPreviousFn = onPrevious.fn;
-    if (!onPrevious.fn)
-      $('.prevButton').attr('disabled', true);
-    this.onNextFn = onNext.fn;
-    if (!onNext.fn)
-      $('.nextButton').attr('disabled', true);
-
-    this.updateSubmitButton();
-
-    if (Viewer.expand) {
-      $('.commentDiv').toggle(true);
-      $('.viewhide').text('Hide comment');
-      $('#expandButton').text('Hide all comments');
-    }
-
-    UI.show('viewerOutput');
-    $('html')[0].scrollIntoView();
-  }
-}
deleted file mode 100644
--- a/mcmerge/js/ViewerController.js
+++ /dev/null
@@ -1,273 +0,0 @@
-"use strict";
-
-var ViewerController = {
-  init: function vc_Init(remap, resume) {
-    this.remap = remap;
-    this.currentStep = -1;
-    this.maxStep = -1;
-    this.steps = [];
-    this.resume = resume;
-  },
-
-
-  getCurrentStep: function vc_getCurrentStep() {
-    if (this.currentStep != -1)
-      return this.steps[this.currentStep];
-  },
-
-
-  removeBug: function vc_RemoveBug(index, bug) {
-    // Remove from attachedBugs
-    this.steps[this.currentStep].detachBugFromCset(index, bug);
-
-    // Call in to viewer
-    Viewer.removeBug(index, bug);
-    Viewer.updateHelpText();
-  },
-
-
-  isValidBugNumber: function vc_IsValidBugNumber(input) {
-    return Config.strictBugNumRE.test(input);
-  },
-
-
-  isValidEmail: function vc_IsValidBugNumber(input) {
-    return Config.emailRE.test(input);
-  },
-
-
-  addBug: function vc_AddBug(index, bug) {
-    UI.hideLoadingOverlay();
-    var step = this.steps[this.currentStep];
-    step.attachBugToCset(index, bug);
-    Viewer.addBug(index, bug);
-    Viewer.updateHelpText();
-  },
-
-
-  onCredentialsEntered: function vc_onCredentialsEntered(uname, pwd) {
-    $('#username')[0].value = '';
-    $('#password')[0].value = '';
-
-    // Verify the email is valid
-    if (Config.needsValidation) {
-      uname = uname.trim();
-      if (!this.isValidEmail(uname)) {
-        UI.showInvalidEmailDialog();
-        return;
-      }
-    }
-
-    // Create privileged loader
-    var options = {username: uname, password: pwd}
-    if (this.remap)
-      options.test = true;
-
-    var privLoader = bz.createClient(options);
-
-    var privilegedUpdate = function(id, data, callback) {
-      privLoader.updateBug(id, data, callback);
-    }
-
-    var privilegedLoad = function(id, callback) {
-      privLoader.getBug(id, callback);
-    }
-
-    Step.privilegedUpdate = privilegedUpdate;
-    Step.privilegedLoad = privilegedLoad;
-    Step.username = uname;
-    this.steps[this.currentStep].onCredentialsAcquired();
-  },
-
-
-  acquireCredentials: function vc_acquireCredentials() {
-    UI.showCredentialsForm();
-  },
-
-
-  onAddBug: function vc_onAddBug(index, input) {
-    UI.showLoadingOverlay();
-
-    // Verify input is valid
-    input = input.trim();
-    if (!this.isValidBugNumber(input)) {
-      UI.showInvalidBugDialog();
-      return;
-    }
-
-    // Verify bug is not already attached
-    if (this.steps[this.currentStep].isAttached(index, input)) {
-      UI.hideLoadingOverlay();
-      return;
-    }
-
-    // Check to see if we already have bug in BugData
-    if (input in BugData.bugs) {
-      this.addBug(index, input);
-      return;
-    }
-
-    // Kick off load if not
-    var self = this;
-    var loadCallback = function vc_onAddBugLoadCallback() {
-      self.addBug(index, input);
-    };
-    BugData.load([input], this.resume, loadCallback, null);
-  },
-
-
-  onChangeBug: function vc_onAddBug(index, bug, input) {
-    UI.showLoadingOverlay();
-
-    // Verify input is valid
-    input = input.trim();
-    if (!this.isValidBugNumber(input)) {
-      UI.showInvalidBugDialog();
-      return;
-    }
-
-    // Verify it's not the same!
-    if (bug == input) {
-      UI.hideLoadingOverlay();
-      Viewer.addChangeButtonListener(cset, bug);
-      return;
-    }
-
-    // If the new bug number is already attached, just delete the old one
-    if (this.steps[this.currentStep].isAttached(index, input)) {
-      UI.hideLoadingOverlay();
-      this.removeBug(index, bug);
-      return;
-    }
-
-    // Check to see if we already have bug in BugData.bugs
-    if (input in BugData.bugs) {
-      this.addBug(index, input);
-      this.removeBug(index, bug);
-      return;
-    }
-
-    // Kick off load if not
-    var self = this;
-    var loadCallback = function vc_onChangeBugLoadCallback() {
-      self.addBug(index, input);
-      self.removeBug(index, bug);
-    };
-    BugData.load([input], this.resume, loadCallback, null);
-  },
-
-
-  onCommentCheckClick: function vc_onCommentCheckClick(index, bug, newVal) {
-    this.steps[this.currentStep].setShouldComment(index, bug, newVal);
-    Viewer.updateHelpText();
-    Viewer.updateSubmitButton();
-  },
-
-
-  onResolveCheckClick: function vc_onResolveCheckClick(bug, newVal) {
-    this.steps[this.currentStep].setShouldResolve(bug, newVal);
-    Viewer.updateHelpText();
-    Viewer.updateSubmitButton();
-  },
-
-
-  onReopenCheckClick: function vc_onReopenCheckClick(bug, newVal) {
-    this.steps[this.currentStep].setShouldReopen(bug, newVal);
-    Viewer.updateSubmitButton();
-  },
-
-
-  onCommentInput: function vc_onCommentInput(index, bug, newVal) {
-    this.steps[this.currentStep].setComment(index, bug, newVal);
-  },
-
-
-  onWhiteboardInput: function vc_onWhiteboardInput(index, bug, newVal) {
-    this.steps[this.currentStep].setWhiteboard(index, bug, newVal.replace(/\n/g, ''));
-  },
-
-
-  onMilestoneChange: function vc_onMilestoneChange(bug, newVal) {
-    this.steps[this.currentStep].setMilestone(bug, newVal);
-  },
-
-
-  onTestsuiteChange: function vc_onTestsuiteChange(bug, newVal) {
-    this.steps[this.currentStep].setTestsuite(bug, newVal);
-  },
-
-
-  postSubmitUpdate: function vc_postSubmitUpdate(index, bug) {
-    Viewer.removeBug(index, bug);
-    Viewer.addBug(index, bug);
-  },
-
-
-  addStep: function vc_addStage(name, isBackedOut) {
-    var step;
-
-    var callbacks = {credentialsCallback: this.acquireCredentials,
-                     uiUpdate: this.postSubmitUpdate};
-
-    step = new Step(name, callbacks, isBackedOut);
-
-    var index = this.steps.push(step) - 1;
-    this.maxStep = this.steps.length;
-    step.setStepNumber(index + 1);
-    for (var i = 0; i < this.maxStep; i++)
-      this.steps[i].setMaxStepNumber(this.maxStep);
-  },
-
-
-  onPrevious: function vc_onPrevious() {
-    this.viewStep(this.currentStep - 1);
-  },
-
-
-  onNext: function vc_onNext() {
-    this.viewStep(this.currentStep + 1);
-  },
-
-
-  viewStep: function vc_viewStep(stepIndex) {
-    this.currentStep = stepIndex;
-    if (stepIndex == this.maxStep) {
-      this.viewSummary();
-      return;
-    }
-
-    var step = this.steps[this.currentStep];
-    var self = this;
-    var onPreviousFn = function vc_viewStepOnPrevious(target) {
-      self.onPrevious();
-    };
-    var onPrevious = {label: 'Previous', fn: onPreviousFn};
-    if (stepIndex == 0)
-      onPrevious.fn = null;
-
-    var onNextfn = function vc_viewStepOnNext(target) {
-      self.onNext();
-    };
-    var onNext = {label: 'Next', fn: onNextfn};
-    if (stepIndex == (this.maxStep - 1))
-      onNext.label = 'Summary';
-
-    Viewer.view(step, onPrevious, onNext);
-  },
-
-
-  viewSummary: function vc_viewSummary() {
-    var self = this;
-    var onPreviousFn = function vc_viewSummaryOnPrevious() {
-      self.onPrevious();
-    };
-    var onPrevious = {label: 'Previous', fn: onPreviousFn};
-
-    var onNextfn = function vc_viewSummaryOnNext() {
-      self.onNext();
-    };
-    var onNext = {label: 'Next', fn: null};
-
-    Summary.view(this.steps, onPrevious, onNext);
-  }
-};
deleted file mode 100644
--- a/mcmerge/js/mcMerge.js
+++ /dev/null
@@ -1,555 +0,0 @@
-"use strict";
-
-var mcMerge = {
-  debug: false,
-  expand: false,
-  remap: false,
-  resume: false,
-  tree: null,
-  trackingFlag: null,
-  statusFlag: null,
-
-  stageTypes: [{name: 'foundBackouts'},
-    {name: 'notFoundBackouts'},
-    {name: 'merges'},
-    {name: 'others'},
-    {name: 'fixes'}
-  ],
-
-
-  init: function mcM_Init() {
-    var self = this;
-    $(window).load(function onDocReady() {
-      if (Config.inMaintenanceMode) {
-        $('#errorText').text('mcMerge is down for maintenance!');
-        UI.show('errors');
-        return;
-      }
-
-      if (Config.supportsHistory) {
-        // Set the popstate handler on a timeout, to avoid the inital load popstate in Webkit
-        window.setTimeout(function mcM_onLoadTimeout() {
-          $(window).on('popstate', {mcMerge: self}, function mcM_InitPopstate(e) {
-           self.parseQuery(e);
-          });
-        }, 1);
-      }
-      self.parseQuery();
-    });
-
-    $(window).unload(function mcM_InitCleanUp() {
-      delete Step.privilegedLoad;
-      delete Step.privilegedUpdate;
-      delete Step.username;
-    });
-  },
-
-
-  // Show the initial cset form, optionally with an error, and
-  // setup a listener to validate input
-  acquireChangeset: function mcM_acquireChangeset(errorText) {
-    delete this.cset;
-    delete this.loading;
-
-    var self = this;
-
-    document.title = 'mcMerge';
-
-    var formListener = function mcM_acquireListener(e) {
-      self.validateForm(e);
-    };
-
-    if (!errorText)
-      UI.showForm(formListener);
-    else
-      UI.showFormWithError(formListener, errorText);
-  },
-
-
-  // Display an appropriate error, then display the cset form
-  errorPage: function mcM_errorPage(params) {
-    var errorType = params['error'];
-    var errorText = 'Unknown error';
-    var cset = 'cset' in params ? ' ' + UI.htmlEncode(params['cset']) : '';
-    var treeName = 'tree' in params ? ' ' + UI.htmlEncode(params['tree']) : '';
-
-    var dataType = 'pushlog';
-    if (this.loading == 'bz')
-      dataType = 'bugzilla';
-    if (this.loading == 'version')
-      dataType = 'target milestone';
-    if (this.loading == 'tracking')
-      dataType = 'tracking and status flag';
-
-    if (errorType == 'invalid')
-      errorText = 'You entered an invalid changeset ID: IDs should either be 12-40 hexadecimal characters, or "tip"';
-
-    if (errorType == 'fetch')
-      errorText = 'Unable to fetch ' + dataType + ' data for changeset' + cset + '.';
-
-    if (errorType == 'timeout')
-      errorText = 'Request timed out when trying to fetch ' + dataType + ' data for changeset' + cset + '.';
-
-    if (errorType == 'buglist')
-      errorText = 'No bugs found for changeset' + cset + '.';
-
-    if (errorType == 'bugs')
-      errorText = 'Unable to load bugzilla data for changeset' + cset + '.';
-
-    if (errorType == 'version')
-      errorText = 'Unable to load target milestone possibilities for changeset' + cset + '.';
-
-    if (errorType == 'treename')
-      errorText = 'Unknown repository' + treeName + '.';
-
-    this.acquireChangeset(errorText);
-  },
-
-
-  ajaxError: function mcM_ajaxError(response, textStatus, errorThrown, cset) {
-    // Ideally, I would use this to provide meaningful error text, if eg cset doesn't exist on m-c.
-    // However, jQuery seems to discard the HTTP 500 error that is returned (jqXHR.status gives 0)
-    // so, we'll need to fallback to generic text
-    if (!cset && this.cset)
-      cset = this.cset;
-
-    if (textStatus == 'timeout')
-      this.go('error=timeout&cset='+cset, false);
-    else
-      this.go('error=fetch&cset='+cset, false);
-  },
-
-
-  // Parse the first merge cset description to try and find out what repo was merged with m-c
-  findSourceRepo: function mcM_findSourceRepo() {
-    var fromRepo = '';
-    var mergeDesc = '';
-    if (PushData.merges[0])
-      mergeDesc = PushData.allPushes[PushData.merges[0]].desc;
-
-    if (!mergeDesc)
-      return '';
-
-    var reArray = new Array();
-
-    // Create the various regular expressions to match repo merges
-    var synonyms = Config.mcSynonyms;
-    for (var i = 0; i < synonyms.length; i++) {
-      var re = new RegExp(Config.repoMergeRE + synonyms[i], 'ig');
-      reArray.push(re);
-      re = new RegExp(synonyms[i] + Config.repoMergeRE, 'ig');
-      reArray.push(re);
-    }
-
-    var reResult = null;
-    for (i = 0; i < reArray.length; i++) {
-      reResult = reArray[i].exec(mergeDesc);
-      if (reResult)
-        break;
-    }
-
-    if (!reResult)
-      return '';
-
-    // We've found text declaring that it's a merge to m-c, can we find another repo name?
-    var otherRepo = '';
-    for (i in Config.treeInfo) {
-      if (i === "mozilla-central")
-        continue;
-
-      synonyms = Config.treeInfo[i].synonyms;
-      for (var j = 0; j < synonyms.length; j++) {
-        if (mergeDesc.indexOf(synonyms[j]) != -1) {
-          otherRepo = i;
-          break;
-        }
-      }
-      if (otherRepo)
-        break;
-    }
-
-    if (otherRepo)
-      return otherRepo;
-
-    return '';
-  },
-
-
-  // Callback following load of bug data from Bugzilla. Providing there's no errors, it's time
-  // to display the UI
-  onBugLoad: function mcM_onBugLoad() {
-    if (!BugData.bugs) {
-      this.go('error=bugs&cset='+this.cset, false);
-      return;
-    }
-
-    this.updateUI();
-  },
-
-
-  // Callback following load of version options from Bugzilla. Checks for errors, then kicks off
-  // bug loading
-  onbzVersionLoad: function mcM_onBZVersionLoad() {
-    if (!ConfigurationData.milestones) {
-      this.go('error=version&cset='+this.cset, false);
-      return;
-    }
-
-    // Don't bother loading bugs for the debug UI
-    if (this.debug) {
-      this.updateUI();
-      return;
-    }
-
-    this.loadBugs();
-  },
-
-
-  // Callback following load of tracking flag names. Kicks off loading of configuration data from BZ
-  onFlagsLoad: function mcM_onFlagLoad(flagData) {
-    UI.hideLoadingMessage();
-    this.trackingFlag = flagData.tracking;
-    this.statusFlag = flagData.status;
-
-    this.loadConfigurationFromBZ();
-  },
-
-
-  // Callback following load of pushlog data. Kicks off loading of current version from m-c
-  onPushlogLoad: function mcM_onPushlogLoad(cset) {
-    UI.hideLoadingMessage();
-
-    if (!PushData.allPushes || PushData.allPushes.length == 0) {
-      this.go('error=fetch&cset='+cset, false);
-      return;
-    }
-
-    if (this.tree === "mozilla-central")
-      UI.sourceRepo = this.findSourceRepo();
-
-    // Stash the changeset requested for future error messages
-    this.cset = cset;
-
-    if (Config.treeInfo[this.tree].trackedTree)
-      this.loadFlags();
-    else
-      this.loadConfigurationFromBZ();
-  },
-
-
-  // Build the list of bugs we're interested in, kick off the async load
-  loadBugs: function mcM_loadBugs() {
-    if (!PushData.allPushes || !PushData.fixes || !PushData.notFoundBackouts)
-      return;
-
-    this.loading = 'bz';
-    UI.showLoadingMessage('Loading Bugzilla data...');
-
-    // Build list of bugs to load
-    var bugArray = [];
-    function forEachCB(val) {
-      var bugNum = this.getBug(val);
-      if (bugArray.indexOf(bugNum) == -1)
-        bugArray.push(bugNum);
-    }
-
-    PushData.fixes.forEach(forEachCB, this);
-    PushData.backedOut.forEach(forEachCB, this);
-
-
-    // Parse commit messages and load backout bugs when the push only contains backouts
-    if (PushData.safeToReopen() && bugArray.length == 0 && PushData.notFoundBackouts.length > 0) {
-      var reResult;
-      for (var i = 0; i < PushData.notFoundBackouts.length; i++) {
-        var ind = PushData.notFoundBackouts[i];
-        PushData.allPushes[ind].backoutBugs = [];
-        Config.bugNumRE.lastIndex = 0;
-         while (reResult = Config.bugNumRE.exec(PushData.allPushes[ind].desc))
-          if (PushData.allPushes[ind].backoutBugs.indexOf(reResult[0]) == -1)
-            PushData.allPushes[ind].backoutBugs.push(reResult[0]);
-        bugArray.push.apply(bugArray, PushData.allPushes[ind].backoutBugs);
-      }
-    }
-
-    // There were no bug numbers found? Might happen when called with a
-    // non-merge "no bug" changeset
-    if (bugArray.length == 0) {
-      this.updateUI();
-      return;
-    }
-
-    var self = this;
-    var loadCallback = function mcM_loadBugsLoadCallback() {
-     self.onBugLoad();
-    };
-
-    var errorCallback = function mcM_loadBugsErrorCallback(jqResponse, textStatus, errorThrown) {
-      self.ajaxError(jqResponse, textStatus, errorThrown);
-    };
-
-    BugData.load(bugArray, this.resume, loadCallback, errorCallback);
-  },
-
-
-  // Load options for options menu from Bugzilla config
-  loadConfigurationFromBZ: function mcM_loadConfigurationFromBZ() {
-    this.loading = 'version';
-    UI.showLoadingMessage('Loading Bugzilla configuration...');
-    var self = this;
-
-    var versionsCallback = function mcM_loadConfigurationLoadCallback() {
-      self.onbzVersionLoad();
-    };
-
-    var errorCallback = function mcM_loadConfigurationErrorCallback(jqResponse, textStatus, errorThrown) {
-      self.ajaxError(jqResponse, textStatus, errorThrown);
-    };
-
-    ConfigurationData.init(versionsCallback, errorCallback);
-  },
-
-
-  loadFlags: function mcM_loadFlags() {
-    this.loading = 'tracking';
-    UI.showLoadingMessage('Calculating tracking/status flags...');
-
-    var self = this;
-    var loadCallback = function mcM_loadFlagsLoadCallback(flagData) {
-     self.onFlagsLoad(flagData);
-    };
-
-    var errorCallback = function mcM_loadFlagsErrorCallback(jqResponse, textStatus, errorThrown) {
-      self.ajaxError(jqResponse, textStatus, errorThrown);
-    };
-
-    var tree = this.tree;
-    FlagLoader.init(this.cset, tree, loadCallback, errorCallback);
-  },
-
-
-  // Load the pushlog for the given cset
-  loadChangeset: function mcM_loadChangeset(cset) {
-    if (!this.validateChangeset(cset)) {
-      this.go('error=invalid', false);
-      return;
-    }
-
-    document.title = 'mcMerge (changeset: ' + cset + ')';
-    this.loading = 'cset';
-    UI.showLoadingMessage('Loading pushlog data...');
-
-    var self = this;
-    var loadCallback = function mcM_loadChangsetLoadCallback(pushData) {
-     self.onPushlogLoad(cset);
-    };
-
-    var errorCallback = function mcM_loadChangesetErrorCallback(jqResponse, textStatus, errorThrown) {
-      self.ajaxError(jqResponse, textStatus, errorThrown, cset);
-    };
-
-    PushData.init(cset, loadCallback, errorCallback);
-  },
-
-
-  getBug: function mcM_getBug(push) {
-    return PushData.allPushes[push].bug;
-  },
-
-
-  showDebugUI: function mcM_debugUI() {
-    DebugUI.displayPushes();
-  },
-
-
-  updateUI: function mcM_updateUI() {
-    UI.hideAll();
-    UI.displayDetail();
-
-    if (this.debug) {
-      this.showDebugUI();
-      return;
-    }
-
-    this.remaps = {items: 0};
-
-    if (this.remap)
-      Remapper.show();
-    else
-      this.showSteps();
-  },
-
-
-  onRemap: function mcM_onRemap(remaps) {
-    this.remaps = remaps;
-    this.showSteps();
-  },
-
-
-  showSteps: function mcM_showSteps() {
-    Step.remaps = this.remaps;
-    Viewer.expand = this.expand;
-    ViewerController.init(this.remap, this.resume);
-    Viewer.init();
-
-    // How many stages do we have?
-    for (var i = 0; i < this.stageTypes.length; i++) {
-      var stageName = this.stageTypes[i].name;
-
-      if (PushData[stageName].length == 0)
-        continue;
-
-      ViewerController.addStep(stageName, stageName == 'foundBackouts');
-    }
-
-    ViewerController.viewStep(0);
-  },
-
-
-  validateChangeset: function mcM_validateChangeset(input) {
-    return Config.csetInputRE.test(input);
-  },
-
-
-  // Verify form content is valid, and try to load it if so
-  validateForm: function mcM_validateForm(e) {
-    e.preventDefault();
-    var input = $('#changeset').attr('value');
-    input = input.trim();
-
-    if (this.validateChangeset(input)) {
-      this.go('cset='+input, false);
-      return;
-    }
-
-    var tree = null;
-
-    for (var treeName in Config.treeInfo) {
-      var reRes = Config.treeInfo[treeName].hgRevRE.exec(input);
-      if (reRes) {
-        input = input.substring(reRes[0].length);
-        tree = treeName;
-        break;
-      } else {
-        reRes = Config.treeInfo[treeName].hgPushlogRE.exec(input);
-        if (reRes) {
-          input = input.substring(reRes[0].length);
-          tree = treeName;
-          break;
-        }
-      }
-    }
-
-    if (tree && this.validateChangeset(input)) {
-      this.go('cset='+input + '&tree=' + tree, false);
-      return;
-    }
-
-    // Don't fill history stack with multiple error pages
-    var replace = document.location.href.indexOf('error') != -1;
-    this.go('error=invalid', replace);
-  },
-
-
-  // Parse URL to display correct content
-  parseQuery: function mcM_parseQuery(event) {
-    var self = null;
-    if (!event)
-      self = this;
-    else
-      self = event.data.mcMerge;
-
-    var query = document.location.search;
-    if (query) {
-      query = query.substring(1);
-      var params = query.split('&');
-      var paramsObj = {}
-      for (var x in params) {
-        var p = params[x].split('=');
-        paramsObj[p[0]] = p[1];
-      }
-      if ('debug' in paramsObj)
-        this.debug = (paramsObj['debug'] == '1');
-      if ('expand' in paramsObj)
-        this.expand = (paramsObj['expand'] == '1');
-      if ('remap' in paramsObj)
-        this.remap = (paramsObj['remap'] == '1');
-      if ('resume' in paramsObj)
-        this.resume = (paramsObj['resume'] == '1');
-
-      if ('error' in paramsObj)
-        return self.errorPage(paramsObj);
-
-      if ('cset' in paramsObj) {
-        var cset = paramsObj['cset'];
-
-        if ('tree' in paramsObj) {
-          var treeName = paramsObj['tree'].toLowerCase();
-          if (!(treeName in Config.treeInfo) && !(treeName in Config.rewriteTrees) &&
-                treeName != 'firefox') {
-            var replace = document.location.href.indexOf('error') != -1;
-            this.go('error=treename&tree=' + treeName, replace);
-            return;
-          }
-
-          if (treeName in Config.rewriteTrees) {
-            var newTree = Config.rewriteTrees[treeName];
-            this.go('cset=' + cset + '&tree=' + newTree, true);
-            return;
-          }
-
-          if (treeName == 'mozilla-central' || treeName == 'firefox') {
-            this.go('cset=' + cset, true);
-            return;
-          }
-
-          this.tree = treeName;
-        } else
-          this.tree = treeName = "mozilla-central";
-
-        Config.hgURL = Config.treeInfo[treeName].hgURL;
-        Config.hgRevURL = Config.treeInfo[treeName].hgRevURL;
-        Config.hgPushlogURL = Config.treeInfo[treeName].hgPushlogURL;
-        Config.treeName = treeName;
-
-        return self.loadChangeset(cset);
-      }
-    }
-    return self.acquireChangeset();
-  },
-
-
-  // Push a new URL onto history
-  go: function mcM_go(query, replace) {
-    var maintained = [];
-    function persist(prop) {
-      if (this[prop])
-        maintained.push(prop + '=1');
-    }
-
-    // Maintain various parameters across page loads
-    var persisted = ['debug', 'expand', 'remap', 'resume'];
-    persisted.forEach(persist, this);
-
-    var newURL = document.location.href.split('?')[0];
-    if (query)
-      newURL = newURL + '?' + query;
-
-    var maintainedQuery = maintained.join('&');
-    if (!query && maintainedQuery.length > 0)
-      newURL += '?';
-    else if (query && maintainedQuery.length > 0)
-      newURL += '&';
-    newURL += maintainedQuery;
-
-    if (Config.supportsHistory) {
-      if (replace)
-        history.replaceState(null, null, newURL);
-      else
-        history.pushState(null, null, newURL);
-      this.parseQuery();
-    } else {
-       document.location.href = newURL;
-    }
-  }
-};
-mcMerge.init();
deleted file mode 100644
--- a/mcmerge/thirdparty/bzjs/bz-0.3.0.js
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
-Copyright (c) 2011 Heather Arthur <fayearthur@gmail.com>
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-*/(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
-// this file is the entrypoint for building a browser file with browserify
-
-bz = require("./bz");
-},{"./bz":2}],2:[function(require,module,exports){
-var BugzillaClient = function(options) {
-  options = options || {};
-  this.username = options.username;
-  this.password = options.password;
-  this.timeout = options.timeout || 0;
-  this.apiUrl = options.url ||
-    (options.test ? "https://bugzilla-dev.allizom.org/bzapi"
-                  : "https://bugzilla.mozilla.org/bzapi");
-  this.apiUrl = this.apiUrl.replace(/\/$/, "");
-}
-
-BugzillaClient.prototype = {
-  getBug : function(id, params, callback) {
-    if (!callback) {
-       callback = params;
-       params = {};
-    }
-    this.APIRequest('/bug/' + id, 'GET', callback, null, null, params);
-  },
-
-  searchBugs : function(params, callback) {
-    this.APIRequest('/bug', 'GET', callback, 'bugs', null, params);
-  },
-
-  countBugs : function(params, callback) {
-    this.APIRequest('/count', 'GET', callback, 'data', null, params);
-  },
-
-  updateBug : function(id, bug, callback) {
-    this.APIRequest('/bug/' + id, 'PUT', callback, 'ok', bug);
-  },
-
-  createBug : function(bug, callback) {
-    this.APIRequest('/bug', 'POST', callback, 'ref', bug);
-  },
-
-  bugComments : function(id, callback) {
-    this.APIRequest('/bug/' + id + '/comment', 'GET', callback, 'comments');
-  },
-
-  addComment : function(id, comment, callback) {
-    this.APIRequest('/bug/' + id + '/comment', 'POST', callback, 'ref', comment);
-  },
-
-  bugHistory : function(id, callback) {
-    this.APIRequest('/bug/' + id + '/history', 'GET', callback, 'history');
-  },
-
-  bugFlags : function(id, callback) {
-    this.APIRequest('/bug/' + id + '/flag', 'GET', callback, 'flags');
-  },
-
-  bugAttachments : function(id, callback) {
-    this.APIRequest('/bug/' + id + '/attachment', 'GET', callback, 'attachments');
-  },
-
-  createAttachment : function(id, attachment, callback) {
-    this.APIRequest('/bug/' + id + '/attachment', 'POST', callback, 'ref', attachment);
-  },
-
-  getAttachment : function(id, callback) {
-    this.APIRequest('/attachment/' + id, 'GET', callback);
-  },
-
-  updateAttachment : function(id, attachment, callback) {
-    this.APIRequest('/attachment/' + id, 'PUT', callback, 'ok', attachment);
-  },
-
-  searchUsers : function(match, callback) {
-    this.APIRequest('/user', 'GET', callback, 'users', null, {match: match});
-  },
-
-  getUser : function(id, callback) {
-    this.APIRequest('/user/' + id, 'GET', callback);
-  },
-
-  getSuggestedReviewers: function(id, callback) {
-    // BMO- specific extension to get suggested reviewers for a given bug
-    // http://bzr.mozilla.org/bmo/4.2/view/head:/extensions/Review/lib/WebService.pm#L102
-    this.APIRequest('/review/suggestions/' + id, 'GET', callback);
-  },
-
-  getConfiguration : function(params, callback) {
-    if (!callback) {
-       callback = params;
-       params = {};
-    }
-    this.APIRequest('/configuration', 'GET', callback, null, null, params);
-  },
-
-  APIRequest : function(path, method, callback, field, body, params) {
-    var url = this.apiUrl + path;
-    if(this.username && this.password) {
-      params = params || {};
-      params.username = this.username;
-      params.password = this.password;
-    }
-    if(params)
-      url += "?" + this.urlEncode(params);
-
-    body = JSON.stringify(body);
-
-    try {
-      //XMLHttpRequest = require("xhr").XMLHttpRequest; // Addon SDK
-    }
-    catch(e) {}
-
-    var that = this;
-    if(typeof XMLHttpRequest != "undefined") {
-      // in a browser
-      var req = new XMLHttpRequest();
-      req.open(method, url, true);
-      req.setRequestHeader("Accept", "application/json");
-      if (method.toUpperCase() !== "GET") {
-        req.setRequestHeader("Content-type", "application/json");
-      }
-      req.onreadystatechange = function (event) {
-        if (req.readyState == 4 && req.status != 0) {
-          that.handleResponse(null, req, callback, field);
-        }
-      };
-      req.timeout = this.timeout;
-      req.ontimeout = function (event) {
-        that.handleResponse('timeout', req, callback);
-      };
-      req.onerror = function (event) {
-        that.handleResponse('error', req, callback);
-      };
-      req.send(body);
-    }
-    else {
-      // node 'request' package
-      //var request = require("request");
-      var requestParams = {
-        uri: url,
-        method: method,
-        body: body,
-        headers: {
-          'Accept': 'application/json',
-          'Content-Type': 'application/json'
-        }
-      };
-      if (this.timeout > 0)
-        requestParams.timeout = this.timeout;
-      request(requestParams, function (err, resp, body) {
-        that.handleResponse(err, {
-            status: resp && resp.statusCode,
-            responseText: body
-          }, callback, field);
-        }
-      );
-    }
-  },
-
-  handleResponse : function(err, response, callback, field) {
-    var error, json;
-    if (err && err.code && (err.code == 'ETIMEDOUT' || err.code == 'ESOCKETTIMEDOUT'))
-      err = 'timeout';
-    else if (err)
-      err = err.toString();
-    if(err)
-      error = err;
-    else if(response.status >= 300 || response.status < 200)
-      error = "HTTP status " + response.status;
-    else {
-      try {
-        json = JSON.parse(response.responseText);
-      } catch(e) {
-        error = "Response wasn't valid json: '" + response.responseText + "'";
-      }
-    }
-    if(json && json.error)
-      error = json.error.message;
-    var ret;
-    if(!error) {
-      ret = field ? json[field] : json;
-      if(field == 'ref') {// creation returns API ref url with id of created object at end
-        var match = ret.match(/(\d+)$/);
-        ret = match ? parseInt(match[0]) : true;
-      }
-    }
-    callback(error, ret);
-  },
-
-  urlEncode : function(params) {
-    var url = [];
-    for(var param in params) {
-      var values = params[param];
-      if(!values.forEach)
-        values = [values];
-      // expand any arrays
-      values.forEach(function(value) {
-         url.push(encodeURIComponent(param) + "=" +
-           encodeURIComponent(value));
-      });
-    }
-    return url.join("&");
-  }
-}
-
-exports.createClient = function(options) {
-  return new BugzillaClient(options);
-}
-
-},{}]},{},[1])
\ No newline at end of file
deleted file mode 100644
--- a/mcmerge/thirdparty/jquery/MIT-LICENSE.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2012 Paul Bakaus, http://jqueryui.com/
-
-This software consists of voluntary contributions made by many
-individuals (AUTHORS.txt, http://jqueryui.com/about) For exact
-contribution history, see the revision history and logs, available
-at http://jquery-ui.googlecode.com/svn/
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
deleted file mode 100644
--- a/mcmerge/thirdparty/jquery/jquery-1.7.2.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! jQuery v1.7.2 jquery.com | jquery.org/license */
-(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(
-a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.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|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f
-.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
\ No newline at end of file
deleted file mode 100644
--- a/mcmerge/thirdparty/toast/grid.css
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-Toast Framework - grid.css
-*/
-.wrap {
-  max-width: 940px;
-  padding: 10px;
-  margin: 0 auto;
-}
-/*
-Column container
-*/
-.grids {
-  width: auto;
-  max-width: 960px;
-  margin: 0 0 0 -1.7%;
-  list-style: none;
-  /* So we can make grids out of lists. */
-
-  overflow: hidden;
-  /* Clear the floats */
-
-}
-.grids [class*="grid-"] {
-  display: inline-block;
-  margin: 0 0 0 1.7%;
-  -webkit-box-sizing: border-box; /* Allow padding & borders on grids without breaking. IE8+ */
-  -moz-box-sizing: border-box;
-  -ms-box-sizing: border-box;
-  -o-box-sizing: border-box;
-  box-sizing: border-box;
-  vertical-align: top;
-}
-.grid-1 {
-  width: 6.15%;
-}
-.grid-2 {
-  width: 14.583%;
-}
-.grid-3 {
-  width: 22.917%;
-}
-.grid-4, .grid-one-third {
-  width: 31.25%;
-}
-.grid-5 {
-  width: 39.583%;
-}
-.grid-6, .grid-half {
-  width: 47.917%;
-}
-.grid-7 {
-  width: 56.25%;
-}
-.grid-8, .grid-two-thirds {
-  width: 64.583%;
-}
-.grid-9 {
-  width: 72.917%;
-}
-.grid-10 {
-  width: 81.25%;
-}
-.grid-11 {
-  width: 89.583%;
-}
-.grid-12 {
-  width: 97.917%;
-  margin: 0;
-}
-@media screen and (max-width: 700px) {
-  .grids {
-    margin: 0;
-    width: auto;
-  }
-  .grids [class*="grid-"] {
-    display: block;
-    width: auto;
-    margin: 0;
-  }
-}
deleted file mode 100644
--- a/mcmerge/thirdparty/toast/reset.css
+++ /dev/null
@@ -1,1 +0,0 @@
-article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;} audio,canvas,video{display:inline;zoom:1;} html{font-size:100%;overflow-y:scroll;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;} body,button,input,select,textarea{font-family:sans-serif;} a:focus{outline:thin dotted;} a:hover,a:active{outline:0;} h1{font-size:2em;} abbr[title]{border-bottom:1px dotted;} b,strong{font-weight:700;} blockquote{margin:1em 40px;} dfn{font-style:italic;} mark{background:#ff9;color:#000;} pre,code,kbd,samp{font-family:monospace, serif;_font-family:'courier new', monospace;font-size:1em;} pre{white-space:pre-wrap;word-wrap:break-word;} q{quotes:none;} q:before,q:after{content:none;} small{font-size:75%;} sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;} sup{top:-.5em;} sub{bottom:-.25em;} ul,ol{margin-left:0;padding:0 0 0 40px;} dd{margin:0 0 0 40px;} nav ul,nav ol{list-style:none;list-style-image:none;} img{border:0;-ms-interpolation-mode:bicubic;} svg:not(:root){overflow:hidden;} fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em;} legend{border:0;margin-left:-7px;} button,input,select,textarea{font-size:inherit;font-family:inherit;line-height:inherit;vertical-align:middle;margin:0;} button,input{line-height:normal;} button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;overflow:visible;} input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0;} input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;} input[type=search]::-webkit-search-decoration{-webkit-appearance:none;} button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;} textarea{overflow:auto;vertical-align:top;} table{border-collapse:collapse;border-spacing:0;} audio:not([controls]),[hidden]{display:none;} body,figure,form{margin:0;}
\ No newline at end of file
deleted file mode 100644
--- a/mcmerge/thirdparty/toast/toast.css
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Toast.css */
-@import url('reset.css');
-@import url('grid.css');
-@import url('type.css');
deleted file mode 100644
--- a/mcmerge/thirdparty/toast/type.css
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Toast Framework - type.css */
-body {
-	font: 100%/1.5 Helvetica Neue, Helvetica, Arial, sans-serif;
-}
-
-h1 {
-    font-size: 3em; /* 48 / 16 */
-    line-height: 1em; /* 48 / 48 */
-    margin-bottom: .5em; /* 24 / 48 */
-}
-h2 {
-    font-size: 2.25em; /* 36 / 16 */
-    line-height: 1.333333333333333em; /* 48 / 36 */
-    margin-bottom: .6666666666666667em; /* 24 / 36 */
-}
-h3 {
-    font-size: 1.5em; /* 24 / 16 */
-    line-height: 1em; /* 24 / 24 */
-    margin-bottom: 1em; /* 24 / 24 */
-}
-h4 {
-    font-size: 1.3125em; /* 21 / 16 */
-    line-height: 1.142857142857143em; /* 24 / 21 */
-    margin-bottom: 1.142857142857143em; /* 24 / 21 */
-}
-h5 {
-    font-size: 1.125em; /* 18 / 16 */
-    line-height: 1.333333333333333em; /* 24 / 18 */
-    margin-bottom: 1.333333333333333em; /* 24 / 18 */
-}
-h6 {
-    font-size: 1em; /* 16 / 16 */
-    line-height: 1.5em; /* 24 / 16 */
-    margin-bottom: 1.5em; /* 24 / 16 */
-}
-p, ul, ol, dl, blockquote {
-    margin-bottom: 1.5em; /* 24 / 16 */
-}
\ No newline at end of file