From f21c4aa346d88e359d63ff301c78b09ac48ee126 Mon Sep 17 00:00:00 2001 From: Rody Davis Date: Tue, 15 Jun 2021 16:21:31 -0700 Subject: [PATCH 01/17] rename .js files to .ts - fixing type errors - adding declared interfaces --- .vscode/settings.json | 6 + app/js/app.js | 96 ----- app/js/app.ts | 100 +++++ app/js/baseCtrl.js | 94 ----- app/js/baseCtrl.ts | 102 +++++ ...anvasDirectives.js => canvasDirectives.ts} | 92 ++--- app/js/config.ts | 8 + app/js/{config_sample.js => config_sample.ts} | 0 app/js/{filters.js => filters.ts} | 13 +- app/js/{gapi.js => gapi.ts} | 34 +- app/js/groupCtrl.js | 58 --- app/js/groupCtrl.ts | 54 +++ ...ctListService.js => projectListService.ts} | 36 +- app/js/{sidebarCtrl.js => sidebarCtrl.ts} | 6 +- app/js/{specCtrl.js => specCtrl.ts} | 119 +++--- .../{specDirectives.js => specDirectives.ts} | 160 ++++---- app/js/specResource.js | 92 ----- app/js/specResource.ts | 107 +++++ app/js/specTabCtrl.js | 366 ----------------- app/js/specTabCtrl.ts | 377 ++++++++++++++++++ app/js/storageService.js | 100 ----- app/js/storageService.ts | 117 ++++++ app/js/userCtrl.js | 61 --- app/js/userCtrl.ts | 59 +++ bower.json | 2 +- tsconfig.json | 71 ++++ 26 files changed, 1246 insertions(+), 1084 deletions(-) create mode 100644 .vscode/settings.json delete mode 100755 app/js/app.js create mode 100755 app/js/app.ts delete mode 100755 app/js/baseCtrl.js create mode 100755 app/js/baseCtrl.ts rename app/js/{canvasDirectives.js => canvasDirectives.ts} (90%) create mode 100644 app/js/config.ts rename app/js/{config_sample.js => config_sample.ts} (100%) rename app/js/{filters.js => filters.ts} (77%) rename app/js/{gapi.js => gapi.ts} (77%) delete mode 100755 app/js/groupCtrl.js create mode 100755 app/js/groupCtrl.ts rename app/js/{projectListService.js => projectListService.ts} (81%) rename app/js/{sidebarCtrl.js => sidebarCtrl.ts} (84%) rename app/js/{specCtrl.js => specCtrl.ts} (57%) rename app/js/{specDirectives.js => specDirectives.ts} (57%) delete mode 100755 app/js/specResource.js create mode 100755 app/js/specResource.ts delete mode 100755 app/js/specTabCtrl.js create mode 100755 app/js/specTabCtrl.ts delete mode 100644 app/js/storageService.js create mode 100644 app/js/storageService.ts delete mode 100755 app/js/userCtrl.js create mode 100755 app/js/userCtrl.ts create mode 100644 tsconfig.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8830e81 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "cSpell.words": [ + "gapi", + "nocheck" + ] +} \ No newline at end of file diff --git a/app/js/app.js b/app/js/app.js deleted file mode 100755 index 9a4d2ee..0000000 --- a/app/js/app.js +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -var config = {}; - -// Import variables if present (from config.js) -if(window){ - Object.assign(config, window.__directConfig); -} - -var app = angular.module('spec', [ - 'ngRoute', - 'ngResource', - 'ngMaterial', - 'ngAnimate', - 'angularytics', - 'environment', - 'LocalStorageModule', - 'ui.sortable' -]); - -app.config(function ($routeProvider) { - $routeProvider - .when('/', { - templateUrl: 'partials/home.html', - }) - .when('/user/:user', { - templateUrl: 'partials/user.html', - controller: 'userCtrl' - }) - .when('/group/:group', { - templateUrl: 'partials/group.html', - controller: 'groupCtrl' - }) - .when('/spec/:id', { - templateUrl: 'partials/spec.html', - controller: 'specCtrl', - reloadOnSearch: false, - resolve: { - validateSpecId: function($route, $location) { - var id = $route.current.params.id; - var multispec = id.split(/\D+/g); - var length = multispec.length; - // filter empty and duplicate - multispec = multispec.filter(function(specId, index) { - return specId.length && multispec.indexOf(specId) == index; - }); - // id was malformed, redirect to cleaned url - if (length !== multispec.length) { - $location.path('/spec/' + multispec.join('+')); - } - } - } - }) - .when('/spec/', { - templateUrl: 'partials/spec.html', - controller: 'specCtrl' - }) - .otherwise({ - redirectTo: '/' - }); -}); - -app.config(function(envServiceProvider) { - envServiceProvider.config({ - domains: { - development: ['localhost'], - staging: [config.stagingDomain], - production: [config.productionDomain], - } - }); - envServiceProvider.check(); -}); - -app.config( function (AngularyticsProvider) { - AngularyticsProvider.setEventHandlers(['Console', 'GoogleUniversal']); -}); - -app.config( function ($mdThemingProvider) { - $mdThemingProvider.theme('spec-head'); -}); - -app.run(['Angularytics', function (Angularytics) { - Angularytics.init(); -}]); diff --git a/app/js/app.ts b/app/js/app.ts new file mode 100755 index 0000000..5e27f3f --- /dev/null +++ b/app/js/app.ts @@ -0,0 +1,100 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const config: { stagingDomain?: string; productionDomain?: string } = {}; + +// Import variables if present (from config.js) +if (window) { + // @ts-ignore + Object.assign(config, window.__directConfig); +} + +const app = angular.module("spec", [ + "ngRoute", + "ngResource", + "ngMaterial", + "ngAnimate", + "angularytics", + "environment", + "LocalStorageModule", + "ui.sortable", +]); + +app.config(function ($routeProvider) { + $routeProvider + .when("/", { + templateUrl: "partials/home.html", + }) + .when("/user/:user", { + templateUrl: "partials/user.html", + controller: "userCtrl", + }) + .when("/group/:group", { + templateUrl: "partials/group.html", + controller: "groupCtrl", + }) + .when("/spec/:id", { + templateUrl: "partials/spec.html", + controller: "specCtrl", + reloadOnSearch: false, + resolve: { + validateSpecId: function ($route, $location) { + var id = $route.current.params.id; + var multispec = id.split(/\D+/g); + var length = multispec.length; + // filter empty and duplicate + multispec = multispec.filter(function (specId, index) { + return specId.length && multispec.indexOf(specId) == index; + }); + // id was malformed, redirect to cleaned url + if (length !== multispec.length) { + $location.path("/spec/" + multispec.join("+")); + } + }, + }, + }) + .when("/spec/", { + templateUrl: "partials/spec.html", + controller: "specCtrl", + }) + .otherwise({ + redirectTo: "/", + }); +}); + +app.config(function (envServiceProvider) { + envServiceProvider.config({ + domains: { + development: ["localhost"], + staging: [config.stagingDomain], + production: [config.productionDomain], + }, + }); + envServiceProvider.check(); +}); + +app.config(function (AngularyticsProvider) { + AngularyticsProvider.setEventHandlers(["Console", "GoogleUniversal"]); +}); + +app.config(function ($mdThemingProvider) { + $mdThemingProvider.theme("spec-head"); +}); + +app.run([ + "Angularytics", + function (Angularytics) { + Angularytics.init(); + }, +]); diff --git a/app/js/baseCtrl.js b/app/js/baseCtrl.js deleted file mode 100755 index b2ccf9e..0000000 --- a/app/js/baseCtrl.js +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -app.controller('baseCtrl', function ($scope, $http, $window, $location, $mdDialog, Spec) { - - $http({ - method: 'GET', - url: '/user' - }).success( function (data, status, headers, config) { - // this callback will be called asynchronously - // when the response is available - $scope.user = data; - }).error( function (data, status, headers, config) { - // called asynchronously if an error occurs - // or server returns response with an error status. - console.warn('> User Request Error'); - console.log(data); - - $window.location.href = '/login'; - }); - - // Helpers - $scope.goto = function (path) { - $location.path(path); - } - - /** - * Project Helpers - */ - - // Duplicate - $scope.duplicateProject = function (ev, project) { - ev.preventDefault(); - ev.stopPropagation(); - - // Clone project data - Spec.get({id: project.id}, function (data) { - var newSpec = { - group: data.group, - groupHandle: data.groupHandle, - title: 'Copy of ' + data.title, - permissions: { - privacy: 'public', - owner: $scope.user, - editors: [], - viewers: [] - }, - spec: data.spec - } - - // Save as new - Spec.save(newSpec, function (resp) { - // Redirect to correct URL - $location.path('/spec/' + resp.id); - }); - }); - } - - // Delete - $scope.deleteProject = function (ev, project, callback) { - ev.preventDefault(); - ev.stopPropagation(); - - // Confirmation - var confirm = $mdDialog.confirm() - .title('Delete Project') - .content('Are you sure you want to delete this project?') - .ok('Yes, delete it') - .cancel('No, nevermind') - .targetEvent(ev); - - $mdDialog.show(confirm).then(function () { - // Delete project - Spec.delete({ id: project.id }, function (resp) { - if (callback) { - callback(); - } - }); - }, function () { - // Project deletion cancelled - }); - } -}); diff --git a/app/js/baseCtrl.ts b/app/js/baseCtrl.ts new file mode 100755 index 0000000..85afe36 --- /dev/null +++ b/app/js/baseCtrl.ts @@ -0,0 +1,102 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +app.controller( + "baseCtrl", + function ($scope, $http, $window, $location, $mdDialog, Spec) { + $http({ + method: "GET", + url: "/user", + }) + .success(function (data, status, headers, config) { + // this callback will be called asynchronously + // when the response is available + $scope.user = data; + }) + .error(function (data, status, headers, config) { + // called asynchronously if an error occurs + // or server returns response with an error status. + console.warn("> User Request Error"); + console.log(data); + + $window.location.href = "/login"; + }); + + // Helpers + $scope.goto = function (path) { + $location.path(path); + }; + + /** + * Project Helpers + */ + + // Duplicate + $scope.duplicateProject = function (ev, project) { + ev.preventDefault(); + ev.stopPropagation(); + + // Clone project data + Spec.get({ id: project.id }, function (data) { + var newSpec = { + group: data.group, + groupHandle: data.groupHandle, + title: "Copy of " + data.title, + permissions: { + privacy: "public", + owner: $scope.user, + editors: [], + viewers: [], + }, + spec: data.spec, + }; + + // Save as new + Spec.save(newSpec, function (resp) { + // Redirect to correct URL + $location.path("/spec/" + resp.id); + }); + }); + }; + + // Delete + $scope.deleteProject = function (ev, project, callback) { + ev.preventDefault(); + ev.stopPropagation(); + + // Confirmation + var confirm = $mdDialog + .confirm() + .title("Delete Project") + .content("Are you sure you want to delete this project?") + .ok("Yes, delete it") + .cancel("No, nevermind") + .targetEvent(ev); + + $mdDialog.show(confirm).then( + function () { + // Delete project + Spec.delete({ id: project.id }, function (resp) { + if (callback) { + callback(); + } + }); + }, + function () { + // Project deletion cancelled + } + ); + }; + } +); diff --git a/app/js/canvasDirectives.js b/app/js/canvasDirectives.ts similarity index 90% rename from app/js/canvasDirectives.js rename to app/js/canvasDirectives.ts index 3443ba9..d9ddee2 100755 --- a/app/js/canvasDirectives.js +++ b/app/js/canvasDirectives.ts @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// @ts-nocheck + /** * Spec Canvas Visuals to render bezier curves and other elements */ @@ -37,27 +39,27 @@ app.directive('specCanvas', function ($timeout) { // Draws the base bar and begin and end circles var drawBar = function (ctx, w, h) { // ctx.fillRect(0, h-10, 2, 10); // Left Bar (debug) - ctx.fillRect(5, h-6, w-10, 2); // Bottom Bar + ctx.fillRect(5, h - 6, w - 10, 2); // Bottom Bar // ctx.fillRect(w-2, h-10, 2, 10); // Right Bar (debug) // Circle Params - var radius = 5; // Arc radius - var startAngle = 0; // Starting point on circle - var endAngle = Math.PI*2; // End point on circle + var radius = 5; // Arc radius + var startAngle = 0; // Starting point on circle + var endAngle = Math.PI * 2; // End point on circle // Left Circle ctx.beginPath(); - ctx.arc(5, h-5, radius, startAngle, endAngle); + ctx.arc(5, h - 5, radius, startAngle, endAngle); ctx.fill(); // Right Circle ctx.beginPath(); - ctx.arc(w-5, h-5, radius, startAngle, endAngle); + ctx.arc(w - 5, h - 5, radius, startAngle, endAngle); ctx.fill(); } - var drawDiamond = function(ctx, w, h) { + var drawDiamond = function (ctx, w, h) { // translate ctx.translate(0, 7); @@ -91,7 +93,7 @@ app.directive('specCanvas', function ($timeout) { } var duration = spec.duration / totalDuration * 100; - var delay = spec.delay / totalDuration * 100; + var delay = spec.delay / totalDuration * 100; wrap.css({ width: duration + '%', @@ -133,55 +135,55 @@ app.directive('specCanvas', function ($timeout) { switch (curve) { case 'curve': ctx.beginPath(); - ctx.moveTo(5, ch-5); - ctx.bezierCurveTo(5, ch-5, cw/2, ((ch-5)*-1), cw-5, ch-5); + ctx.moveTo(5, ch - 5); + ctx.bezierCurveTo(5, ch - 5, cw / 2, ((ch - 5) * -1), cw - 5, ch - 5); ctx.fill(); break; case 'quantum': inValue = 0.8; outValue = 0.4; ctx.beginPath(); - ctx.moveTo(5, ch-5); - ctx.bezierCurveTo( (cw*outValue)+5, ch-5, ((1-inValue)*cw)-5, 0, cw-5, 0); - ctx.lineTo(cw-5, ch-5); + ctx.moveTo(5, ch - 5); + ctx.bezierCurveTo((cw * outValue) + 5, ch - 5, ((1 - inValue) * cw) - 5, 0, cw - 5, 0); + ctx.lineTo(cw - 5, ch - 5); ctx.fill(); break; case 'incoming': inValue = 0.8; outValue = 0; ctx.beginPath(); - ctx.moveTo(5, ch-5); - ctx.bezierCurveTo( (cw*outValue)+5, ch-5, ((1-inValue)*cw)-5, 0, cw-5, 0); - ctx.lineTo(cw-5, ch-5); + ctx.moveTo(5, ch - 5); + ctx.bezierCurveTo((cw * outValue) + 5, ch - 5, ((1 - inValue) * cw) - 5, 0, cw - 5, 0); + ctx.lineTo(cw - 5, ch - 5); ctx.fill(); break; case 'outgoing': inValue = 0; outValue = 0.4; ctx.beginPath(); - ctx.moveTo(5, ch-5); - ctx.bezierCurveTo( (cw*outValue)+5, ch-5, ((1-inValue)*cw)-5, 0, cw-5, 0); - ctx.lineTo(cw-5, ch-5); + ctx.moveTo(5, ch - 5); + ctx.bezierCurveTo((cw * outValue) + 5, ch - 5, ((1 - inValue) * cw) - 5, 0, cw - 5, 0); + ctx.lineTo(cw - 5, ch - 5); ctx.fill(); break; case 'linear': ctx.beginPath(); - ctx.moveTo(5, ch-5); - ctx.lineTo(cw-5, 0); - ctx.lineTo(cw-5, ch-5); + ctx.moveTo(5, ch - 5); + ctx.lineTo(cw - 5, 0); + ctx.lineTo(cw - 5, ch - 5); ctx.fill(); break; case 'custom': inValue = spec.easingCustomIncoming / 100; outValue = spec.easingCustomOutgoing / 100; ctx.beginPath(); - ctx.moveTo(5, ch-5); - ctx.bezierCurveTo( (cw*outValue)+5, ch-5, ((1-inValue)*cw)-5, 0, cw-5, 0); - ctx.lineTo(cw-5, ch-5); + ctx.moveTo(5, ch - 5); + ctx.bezierCurveTo((cw * outValue) + 5, ch - 5, ((1 - inValue) * cw) - 5, 0, cw - 5, 0); + ctx.lineTo(cw - 5, ch - 5); ctx.fill(); break; case 'none': - ctx.fillRect(5, 0, cw-10, ch-5); + ctx.fillRect(5, 0, cw - 10, ch - 5); break; default: break; @@ -208,7 +210,7 @@ app.directive('specCanvas', function ($timeout) { }, true); // Window Width Changes - $(window).resize( function () { + $(window).resize(function () { render(wrap, canvas, scope.specCanvas, scope.duration); }); @@ -282,8 +284,8 @@ app.directive('specGrid', function ($timeout) { ctx.lineTo(1, ch); // Always draw end - ctx.moveTo(cw-1, 0); - ctx.lineTo(cw-1, ch); + ctx.moveTo(cw - 1, 0); + ctx.lineTo(cw - 1, ch); ctx.strokeStyle = '#DDDDDD'; ctx.lineWidth = 2; @@ -306,7 +308,7 @@ app.directive('specGrid', function ($timeout) { }, true); // Window Width Changes - $(window).resize( function () { + $(window).resize(function () { if (scope.specGrid && scope.specGrid !== undefined) { render(canvas, scope.specGrid); } @@ -388,8 +390,8 @@ app.directive('specDraw', function ($timeout, $document) { // Draw end if the duration is a multiple of 75ms if (ms % majorMs === 0) { - ctx.moveTo(cw-1, 0); - ctx.lineTo(cw-1, ch); + ctx.moveTo(cw - 1, 0); + ctx.lineTo(cw - 1, ch); } ctx.strokeStyle = '#E9E0EB'; @@ -401,10 +403,10 @@ app.directive('specDraw', function ($timeout, $document) { var ctx = canvas.get(0).getContext('2d'); ctx.beginPath(); - var y = 30; // y coordinate - var radius = 5; // Arc radius - var startAngle = 0; // Starting point on circle - var endAngle = Math.PI*2; // End point on circle + var y = 30; // y coordinate + var radius = 5; // Arc radius + var startAngle = 0; // Starting point on circle + var endAngle = Math.PI * 2; // End point on circle ctx.arc(x, y, radius, startAngle, endAngle); ctx.fillStyle = '#CE93D8'; @@ -492,17 +494,17 @@ app.directive('specDraw', function ($timeout, $document) { $document.on('mouseup', mouseup); }); - var inBounds = function(event) { + var inBounds = function (event) { var y = event.pageY; var x = event.pageX; - var offsetLeft = getLeft(element[0])-x; - var offsetTop = getTop(element[0])-y; + var offsetLeft = getLeft(element[0]) - x; + var offsetTop = getTop(element[0]) - y; var padding = 20; - if ((offsetLeft > padding || offsetLeft < -canvas.width()-padding) || - (offsetTop > padding || offsetTop < -canvas.height()-padding)) { - return false; + if ((offsetLeft > padding || offsetLeft < -canvas.width() - padding) || + (offsetTop > padding || offsetTop < -canvas.height() - padding)) { + return false; } return true; @@ -607,7 +609,7 @@ app.directive('specDraw', function ($timeout, $document) { }, true); // Window Width Changes - $(window).resize( function () { + $(window).resize(function () { if (scope.specDraw && scope.specDraw !== undefined) { render(canvas, scope.specDraw); } @@ -631,7 +633,7 @@ app.directive('specDraw', function ($timeout, $document) { app.directive('specTip', function () { var render = function (tip, spec, totalDuration) { var duration = spec.duration / totalDuration; - var delay = spec.delay / totalDuration; + var delay = spec.delay / totalDuration; var containerWidth = $('.spec-item-wrap').width(); var offset = delay + (duration / 2); var pixelOffset = offset * containerWidth; @@ -658,7 +660,7 @@ app.directive('specTip', function () { }, true); // Window Width Changes - $(window).resize( function () { + $(window).resize(function () { render(tip, scope.specTip, scope.duration); }); } diff --git a/app/js/config.ts b/app/js/config.ts new file mode 100644 index 0000000..5285805 --- /dev/null +++ b/app/js/config.ts @@ -0,0 +1,8 @@ +(function (window) { + window.__directConfig = window.__directConfig || {}; + + window.__directConfig.stagingDomain = 'staging.example.com'; + window.__directConfig.productionDomain = 'example.com'; + +}(this)); + diff --git a/app/js/config_sample.js b/app/js/config_sample.ts similarity index 100% rename from app/js/config_sample.js rename to app/js/config_sample.ts diff --git a/app/js/filters.js b/app/js/filters.ts similarity index 77% rename from app/js/filters.js rename to app/js/filters.ts index 1861a6a..074a4e9 100755 --- a/app/js/filters.js +++ b/app/js/filters.ts @@ -12,8 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -app.filter('nl2br', ['$sce', function ($sce) { - return function (text) { - return text ? $sce.trustAsHtml(text.replace(/\n/g, '
')) : ''; - }; -}]); +app.filter("nl2br", [ + "$sce", + function ($sce) { + return function (text) { + return text ? $sce.trustAsHtml(text.replace(/\n/g, "
")) : ""; + }; + }, +]); diff --git a/app/js/gapi.js b/app/js/gapi.ts similarity index 77% rename from app/js/gapi.js rename to app/js/gapi.ts index 5dfdd07..aa58371 100644 --- a/app/js/gapi.js +++ b/app/js/gapi.ts @@ -16,18 +16,22 @@ These API keys are Javascript API keys that must be included client side. We have an HTTP referrer whitelist server-side to prevent quota misuse. */ -var developerKey = 'AIzaSyAwMg3spfEqfQyCUR1OXfyCAse3GzxpxJM'; -var clientId = "103309234391-nak808obap92p3i1cslqi1oubsfnub1m.apps.googleusercontent.com" +var developerKey = "AIzaSyAwMg3spfEqfQyCUR1OXfyCAse3GzxpxJM"; +var clientId = + "103309234391-nak808obap92p3i1cslqi1oubsfnub1m.apps.googleusercontent.com"; var appId = "103309234391"; -var scope = ['https://www.googleapis.com/auth/drive.readonly']; +var scope = ["https://www.googleapis.com/auth/drive.readonly"]; var pickerApiLoaded = false; var oauthToken; var scopeModel; +declare const gapi; +declare const google; + function onApiLoad() { - gapi.load('auth'); - gapi.load('picker', {'callback': onPickerApiLoad}); + gapi.load("auth"); + gapi.load("picker", { callback: onPickerApiLoad }); } function loadPicker(model) { @@ -36,11 +40,15 @@ function loadPicker(model) { } function authorize(immediate) { - window.gapi.auth.authorize({ - 'client_id': clientId, - 'scope': scope, - 'immediate': immediate - }, showPicker); + // @ts-ignore + window.gapi.auth.authorize( + { + client_id: clientId, + scope: scope, + immediate: immediate, + }, + showPicker + ); } function onPickerApiLoad() { @@ -64,13 +72,13 @@ function showPicker(authResult) { .setOAuthToken(oauthToken) .setDeveloperKey(developerKey) .setCallback(pickerCallback) - .setTitle('Select a Video') + .setTitle("Select a Video") .build(); picker.setVisible(true); } - } else if (authResult.error === 'immediate_failed') { + } else if (authResult.error === "immediate_failed") { debugger; - authorize(false) + authorize(false); } } diff --git a/app/js/groupCtrl.js b/app/js/groupCtrl.js deleted file mode 100755 index 813c677..0000000 --- a/app/js/groupCtrl.js +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -app.controller('groupCtrl', function ( - $scope, - $routeParams, - Spec, - projectListService) { - - // Config - $scope.hasProjects = true; - $scope.projectGroups = []; - $scope.selected = []; - - var groupHandle = $routeParams.group.replace(/\s+/g, '-').toLowerCase(); - - Spec.query({group: groupHandle}, function (specs) { - - // Show new project message if necessary - if (specs.length < 1) { - $scope.hasProjects = false; - } - - angular.forEach(specs, function (spec, index) { - projectListService.addProject($scope, spec); - }); - - }); - - $scope.toggleSelected = function(item) { - projectListService.toggleSelected($scope, item); - }; - - $scope.isSelected = function(item) { - return projectListService.isSelected($scope, item); - }; - - $scope.selectedToRouteParam = function() { - return projectListService.selectedToRouteParam($scope); - } - - $scope.deleteProject = function(ev, project) { - $scope.$parent.deleteProject(ev, project, function() { - projectListService.deleteProject($scope, project); - }); - } -}); diff --git a/app/js/groupCtrl.ts b/app/js/groupCtrl.ts new file mode 100755 index 0000000..c21856b --- /dev/null +++ b/app/js/groupCtrl.ts @@ -0,0 +1,54 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +app.controller( + "groupCtrl", + function ($scope, $routeParams, Spec, projectListService) { + // Config + $scope.hasProjects = true; + $scope.projectGroups = []; + $scope.selected = []; + + var groupHandle = $routeParams.group.replace(/\s+/g, "-").toLowerCase(); + + Spec.query({ group: groupHandle }, function (specs) { + // Show new project message if necessary + if (specs.length < 1) { + $scope.hasProjects = false; + } + + angular.forEach(specs, function (spec, index) { + projectListService.addProject($scope, spec); + }); + }); + + $scope.toggleSelected = function (item) { + projectListService.toggleSelected($scope, item); + }; + + $scope.isSelected = function (item) { + return projectListService.isSelected($scope, item); + }; + + $scope.selectedToRouteParam = function () { + return projectListService.selectedToRouteParam($scope); + }; + + $scope.deleteProject = function (ev, project) { + $scope.$parent.deleteProject(ev, project, function () { + projectListService.deleteProject($scope, project); + }); + }; + } +); diff --git a/app/js/projectListService.js b/app/js/projectListService.ts similarity index 81% rename from app/js/projectListService.js rename to app/js/projectListService.ts index e9d17db..359432d 100644 --- a/app/js/projectListService.js +++ b/app/js/projectListService.ts @@ -12,16 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -app.service('projectListService', function() { - +app.service("projectListService", function () { // multispec selection this.toggleSelected = function ($scope, item) { var idx = $scope.selected.indexOf(item); if (idx > -1) { $scope.selected.splice(idx, 1); - } - else { + } else { $scope.selected.push(item); } }; @@ -30,10 +28,12 @@ app.service('projectListService', function() { return $scope.selected.indexOf(item) > -1; }; - this.selectedToRouteParam = function($scope) { - return $scope.selected.map(function(spec) { - return spec.id; - }).join('+'); + this.selectedToRouteParam = function ($scope) { + return $scope.selected + .map(function (spec) { + return spec.id; + }) + .join("+"); }; // project list construction @@ -42,12 +42,14 @@ app.service('projectListService', function() { var i = $scope.projectGroups.length; var projectAdded = false; - spec.group = spec.group || ''; + spec.group = spec.group || ""; // Loop through all groups while (i--) { // If title matches, add to projects array - if ($scope.projectGroups[i].title.toLowerCase() === spec.group.toLowerCase()) { + if ( + $scope.projectGroups[i].title.toLowerCase() === spec.group.toLowerCase() + ) { $scope.projectGroups[i].projects.push(spec); projectAdded = true; } @@ -58,17 +60,20 @@ app.service('projectListService', function() { var grp = { title: spec.group, projects: [], - handle: spec.group - } + handle: spec.group, + }; grp.projects.push(spec); $scope.projectGroups.push(grp); } - } + }; this.deleteProject = function ($scope, project) { for (var i = 0; i < $scope.projectGroups.length; i++) { - if ($scope.projectGroups[i].title.toLowerCase() === project.group.toLowerCase()) { + if ( + $scope.projectGroups[i].title.toLowerCase() === + project.group.toLowerCase() + ) { var group = $scope.projectGroups[i]; // Delete project from array @@ -90,8 +95,7 @@ app.service('projectListService', function() { } } } - } } - } + }; }); diff --git a/app/js/sidebarCtrl.js b/app/js/sidebarCtrl.ts similarity index 84% rename from app/js/sidebarCtrl.js rename to app/js/sidebarCtrl.ts index 91576df..d868a42 100755 --- a/app/js/sidebarCtrl.js +++ b/app/js/sidebarCtrl.ts @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -app.controller('sidebarCtrl', function ($scope, Spec, projectListService) { +app.controller("sidebarCtrl", function ($scope, Spec, projectListService) { // Project Listing for Sidebar // Updates sidebar with new items and edits - $scope.$on('refreshSidebar', function() { + $scope.$on("refreshSidebar", function () { $scope.projectGroups = []; - Spec.query({owner: $scope.user}, function (specs) { + Spec.query({ owner: $scope.user }, function (specs) { $scope.projectGroups = []; angular.forEach(specs, function (spec, index) { projectListService.addProject($scope, spec); diff --git a/app/js/specCtrl.js b/app/js/specCtrl.ts similarity index 57% rename from app/js/specCtrl.js rename to app/js/specCtrl.ts index 8863257..98145d8 100755 --- a/app/js/specCtrl.js +++ b/app/js/specCtrl.ts @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -app.controller('specCtrl', function ($scope, $routeParams, $sce, $location) { +app.controller("specCtrl", function ($scope, $routeParams, $sce, $location) { // Initial Config $scope.uiState = { overlay: false, sidebar: false, saveInProgress: false, - showingEmbedPopup: false + showingEmbedPopup: false, }; // Constants @@ -29,22 +29,21 @@ app.controller('specCtrl', function ($scope, $routeParams, $sce, $location) { // Initial Data Setup if ($routeParams.id) { $scope.multispec = $routeParams.id.split(/\D+/g); - } - else { - $scope.multispec = [ null ]; // create an empty spec for editing + } else { + $scope.multispec = [null]; // create an empty spec for editing } if ($routeParams.embed) { $scope.embedded = true; } - $scope.embedUrl = $location.absUrl().split('?')[0] + '?embed'; + $scope.embedUrl = $location.absUrl().split("?")[0] + "?embed"; // UI state $scope.showSidebar = function () { $scope.uiState.sidebar = true; $scope.uiState.overlay = true; - } + }; $scope.closeOverlay = function () { // Close sidebar @@ -55,106 +54,118 @@ app.controller('specCtrl', function ($scope, $routeParams, $sce, $location) { // Close overlay $scope.uiState.overlay = false; - } + }; $scope.toggleEmbedPopup = function () { $scope.uiState.showingEmbedPopup = !$scope.uiState.showingEmbedPopup; $scope.uiState.overlay = $scope.uiState.showingEmbedPopup; - } + }; // Manually redraw grid and grid items - $scope.refreshCanvas = (function () { - $scope.$broadcast('refreshCanvas'); - }).debounce(100); + $scope.refreshCanvas = function () { + $scope.$broadcast("refreshCanvas"); + } + // @ts-ignore + .debounce(100); // reload project list in menu (see sidebarCtrl.js) - $scope.refreshSidebar = (function() { - $scope.$broadcast('refreshSidebar'); - }).debounce(100); + $scope.refreshSidebar = function () { + $scope.$broadcast("refreshSidebar"); + } + // @ts-ignore + .debounce(100); // Helpers - $scope.deleteProject = function(ev, data) { - $scope.$parent.deleteProject(ev, data, function() { + $scope.deleteProject = function (ev, data) { + $scope.$parent.deleteProject(ev, data, function () { if ($scope.multispec.length > 1) { var deletedIdx = $scope.multispec.indexOf(data.id.toString()); if (deletedIdx > -1) { $scope.multispec.splice(deletedIdx, 1); } - $scope.goto('/spec/' + $scope.multispec.join('+')); - } - else { - $scope.goto('/user/' + $scope.user); + $scope.goto("/spec/" + $scope.multispec.join("+")); + } else { + $scope.goto("/user/" + $scope.user); } }); - } + }; // Constants // Colors - $scope.colors = ['#E51C23', '#9C27B0', '#5677FC', '#00BCD4', '#259B24', '#CDDC39', '#FFC107', '#795548', '#737373']; + $scope.colors = [ + "#E51C23", + "#9C27B0", + "#5677FC", + "#00BCD4", + "#259B24", + "#CDDC39", + "#FFC107", + "#795548", + "#737373", + ]; // Easing $scope.easingOptions = [ { - label: '80% Incoming, 40% Outgoing', - value: 'quantum' + label: "80% Incoming, 40% Outgoing", + value: "quantum", }, { - label: '80% Incoming Only', - value: 'incoming' + label: "80% Incoming Only", + value: "incoming", }, { - label: '40% Outgoing Only', - value: 'outgoing' + label: "40% Outgoing Only", + value: "outgoing", }, { - label: 'Linear', - value: 'linear' + label: "Linear", + value: "linear", }, { - label: 'Custom Curve', - value: 'custom' - } + label: "Custom Curve", + value: "custom", + }, ]; // Property Tags $scope.tagOptions = [ { - label: 'Position-x', - value: 'position-x' + label: "Position-x", + value: "position-x", }, { - label: 'Position-y', - value: 'position-y' + label: "Position-y", + value: "position-y", }, { - label: 'Position-xy', - value: 'position-xy' + label: "Position-xy", + value: "position-xy", }, { - label: 'Scale', - value: 'scale' + label: "Scale", + value: "scale", }, { - label: 'Opacity', - value: 'opacity' + label: "Opacity", + value: "opacity", }, { - label: 'Rotation', - value: 'rotation' + label: "Rotation", + value: "rotation", }, { - label: 'Mask', - value: 'mask' + label: "Mask", + value: "mask", }, { - label: 'Custom', - value: 'custom' + label: "Custom", + value: "custom", }, { - label: 'None', - value: 'none' - } + label: "None", + value: "none", + }, ]; - }); diff --git a/app/js/specDirectives.js b/app/js/specDirectives.ts similarity index 57% rename from app/js/specDirectives.js rename to app/js/specDirectives.ts index 650f3b6..e42b054 100644 --- a/app/js/specDirectives.js +++ b/app/js/specDirectives.ts @@ -12,109 +12,110 @@ // See the License for the specific language governing permissions and // limitations under the License. +// @ts-nocheck + /* * initializes wrapperElem for specTabCtrl scope * element is a jqLite wrapper around an element with class=spec-tab-ctrl-wrap */ -app.directive('specTabCtrlWrap', function () { +app.directive("specTabCtrlWrap", function () { return { - restrict: 'C', + restrict: "C", link: function ($scope, element, attrs) { $scope.wrapperElem = element; - } - } + }, + }; }); /* * enables drag-to-reorder rows, * and clicking outside of containment to close drawer */ -app.directive('specGridContainment', function () { +app.directive("specGridContainment", function () { return { - restrict: 'C', + restrict: "C", link: function ($scope, element, attrs) { // options for drag-to-reorder rows $scope.sortableOptions = { - axis: 'y', - handle: '.item-canvas', - tolerance: 'pointer', + axis: "y", + handle: ".item-canvas", + tolerance: "pointer", disabled: !$scope.editing, - containment: element + containment: element, }; - $scope.$watch('editing', function() { + $scope.$watch("editing", function () { $scope.sortableOptions.disabled = !$scope.editing; }); - } - } + }, + }; }); /* * sizes the spec property tags on the timeline view */ -app.directive('specPropertyTagSizer', function ($timeout) { +app.directive("specPropertyTagSizer", function ($timeout) { return { - restrict: 'A', + restrict: "A", link: function ($scope, element, attrs) { var updateSize = function () { - var itemCanvasWrap = element.parent('.item-canvas-wrap'); + var itemCanvasWrap = element.parent(".item-canvas-wrap"); if (itemCanvasWrap.width() > 200) { - element.css('max-width', '100%'); - } - else { - element.css('max-width', 200); + element.css("max-width", "100%"); + } else { + element.css("max-width", 200); - var canvasMargin = itemCanvasWrap.outerWidth(true) - - itemCanvasWrap.outerWidth(); - var specItem = element.closest('.spec-item'); + var canvasMargin = + itemCanvasWrap.outerWidth(true) - itemCanvasWrap.outerWidth(); + var specItem = element.closest(".spec-item"); if (canvasMargin + element.outerWidth() > specItem.width()) { - var offset = specItem.width() - (canvasMargin + element.outerWidth()); + var offset = + specItem.width() - (canvasMargin + element.outerWidth()); if (Math.abs(offset) < canvasMargin) { - element.css('margin-left', offset); - } - else { - element.css('margin-left', 0); + element.css("margin-left", offset); + } else { + element.css("margin-left", 0); } } } }; $(window).resize(updateSize); $(document).ready(updateSize); - } - } + }, + }; }); /** * Allow stepping through video with arrow keys */ -app.directive('scrubbable', function () { - +app.directive("scrubbable", function () { return { - restrict: 'A', + restrict: "A", link: function (scope, element, attrs) { var video = element[0]; /* timeline video scrubbing */ - var gridContainment = $(element[0]).parents('.spec-content') - .find('.spec-grid-containment'); + var gridContainment = $(element[0]) + .parents(".spec-content") + .find(".spec-grid-containment"); // convert between timestamp in seconds to pixels from left edge of spec - var secondsToX = function(videoSeconds) { + var secondsToX = function (videoSeconds) { var videoMs = videoSeconds * 1000; var numMinorDivisions = videoMs / scope.spec.divisions.minor; var coordinateX = numMinorDivisions * scope.spec.divisions.minorGap; return coordinateX; - } + }; - var xToSeconds = function(coordinateX) { + var xToSeconds = function (coordinateX) { var ms = scope.spec.divisions.minor; var mGap = scope.spec.divisions.minorGap; var timestampMs = (coordinateX / mGap) * ms; var timestampSeconds = timestampMs * 0.001; return timestampSeconds; - } + }; - var onTimeUpdate = function() { + var onTimeUpdate = function () { var x = secondsToX(video.currentTime); moveScrubber(x); updateTimestamp(); @@ -123,21 +124,21 @@ app.directive('scrubbable', function () { } }; - var updateTimestamp = (function() { + var updateTimestamp = function () { // request angular to update value for video.currentTime in UI scope.$apply(); - }).throttle(); // rate limit this event to one / 100ms (to prevent ui lag) + }.throttle(); // rate limit this event to one / 100ms (to prevent ui lag) - video.addEventListener('seeking', function() { + video.addEventListener("seeking", function () { window.requestAnimationFrame(onTimeUpdate); }); - video.addEventListener('play', function() { + video.addEventListener("play", function () { window.requestAnimationFrame(onTimeUpdate); }); - var constrainScrubberX = function(x) { - var gridWidth = $(gridContainment).find('.spec-grid').width(); + var constrainScrubberX = function (x) { + var gridWidth = $(gridContainment).find(".spec-grid").width(); var durationX = secondsToX(video.duration); var maxAllowedX = Math.min(durationX, gridWidth); x = Math.min(x, maxAllowedX); @@ -145,16 +146,16 @@ app.directive('scrubbable', function () { return x; }; - var scrubber = $(gridContainment).find('.spec-grid-scrubber'); - var moveScrubber = function(x) { + var scrubber = $(gridContainment).find(".spec-grid-scrubber"); + var moveScrubber = function (x) { if (!scrubber.length) { - scrubber = $(gridContainment).find('.spec-grid-scrubber'); + scrubber = $(gridContainment).find(".spec-grid-scrubber"); } scope.refreshCanvas(); - scrubber.css('left', constrainScrubberX(x)); + scrubber.css("left", constrainScrubberX(x)); }; - var scrubVideoX = (function (x) { + var scrubVideoX = function (x) { var timestampSeconds = xToSeconds(x); if (timestampSeconds < video.duration) { @@ -164,59 +165,58 @@ app.directive('scrubbable', function () { video.currentTime = timestampSeconds; window.requestAnimationFrame(onTimeUpdate); } - }).throttle(); // rate limit this event to one / 100ms (to prevent ui lag) + }.throttle(); // rate limit this event to one / 100ms (to prevent ui lag) // listen to mouse events on the scrub handle - $(gridContainment) - .one('mouseover', '.spec-grid-scrubber', function() { - var scrubber = $(this); - scrubber.draggable({ - axis: 'x', - cursorAt: { left: 0 }, - drag: function(evt, ui) { - ui.position.left = constrainScrubberX(ui.position.left); - scrubVideoX(ui.position.left); - } - }); + $(gridContainment).one("mouseover", ".spec-grid-scrubber", function () { + var scrubber = $(this); + scrubber.draggable({ + axis: "x", + cursorAt: { left: 0 }, + drag: function (evt, ui) { + ui.position.left = constrainScrubberX(ui.position.left); + scrubVideoX(ui.position.left); + }, }); + }); // show warning message if durations don't match - var checkDurationMatch = function() { + var checkDurationMatch = function () { if (video.duration && scope.spec.duration) { - var warn = Math.abs(video.duration * 1000 - scope.spec.duration) > 100; + var warn = + Math.abs(video.duration * 1000 - scope.spec.duration) > 100; scope.toggleVideoWarning(warn); scope.setCanScrubVideo(!warn); } }; - scope.$watch('spec.duration', checkDurationMatch); - video.addEventListener('durationchange', checkDurationMatch); - } - } + scope.$watch("spec.duration", checkDurationMatch); + video.addEventListener("durationchange", checkDurationMatch); + }, + }; }); -app.directive('loadedData', function () { +app.directive("loadedData", function () { return function ($scope, $element) { var parentScope = $scope.$parent; parentScope.video = $element[0]; - parentScope.video.addEventListener('loadeddata', function () { - console.log('Video loaded'); - $scope.$parent.$broadcast('refreshCanvas'); + parentScope.video.addEventListener("loadeddata", function () { + console.log("Video loaded"); + $scope.$parent.$broadcast("refreshCanvas"); // attach functions to video play controls - parentScope.toggleVideoLooping = function() { + parentScope.toggleVideoLooping = function () { parentScope.video.loop = !parentScope.video.loop; - } + }; - parentScope.toggleVideoPaused = function() { + parentScope.toggleVideoPaused = function () { if (parentScope.video.paused) { parentScope.video.play(); - } - else { + } else { parentScope.video.pause(); } - } + }; }); - } + }; }); diff --git a/app/js/specResource.js b/app/js/specResource.js deleted file mode 100755 index dbeeb36..0000000 --- a/app/js/specResource.js +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -app.provider('Spec', function () { - this.$get = ['$resource', 'envService', 'localStorageService', '$timeout', - function ($resource, envService, localStorageService, $timeout) { - - if (envService.is('production')) { - var Spec = $resource('/api/spec/:id', {}, { - update: { - method: 'PUT' - } - }); - } - else { - // not on a production environment, return mocked Spec with localStorage - var Spec = { - query: function(params, callback) { - console.log('localstorage query'); - $timeout(function() { // simulate async so the callback works - var specs = []; - var lsKeys = localStorageService.keys(); - lsKeys.forEach(function(lsKey) { - var spec = localStorageService.get(lsKey); - var flat = { - group: spec.groupHandle, // match on groupHandle - id: spec.id, - owner: spec.permissions.owner, - privacy: spec.permissions.privacy, - timestamp: Date.now() / 1000 | 0, - title: spec.title - }; - var isMatch = Object.keys(params).every(function(paramKey) { - return flat[paramKey] == params[paramKey]; - }); - if (isMatch) { - flat.group = spec.group; // return group name - specs.push(flat); - } - }); - callback(specs); - }, 0); - }, - get: function(params, callback) { - console.log('localstorage get'); - $timeout(function() { // simulate async so the callback works - var data = localStorageService.get(params.id); - callback(data); - }, 0); - }, - save: function(value, callback) { - console.log('localstorage save'); - $timeout(function() { // simulate async so the callback works - var id = Math.round(Math.random() * 100000000); - while (localStorageService.get(id)) id = Math.round(Math.random() * 100000000); - - value.id = id; - localStorageService.set(id, value); - callback({id: id}); - }, 0); - }, - update: function(params, value, callback) { - $timeout(function() { // simulate async so the callback works - console.log('localstorage update'); - localStorageService.set(params.id, value); - callback(value); - }, 0); - }, - delete: function(params, callback) { - console.log('localstorage delete'); - $timeout(function() { // simulate async so the callback works - localStorageService.remove(params.id); - callback({}); - }, 0); - }, - }; - } - - return Spec; - }]; -}); diff --git a/app/js/specResource.ts b/app/js/specResource.ts new file mode 100755 index 0000000..df76e6b --- /dev/null +++ b/app/js/specResource.ts @@ -0,0 +1,107 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +app.provider("Spec", function () { + this.$get = [ + "$resource", + "envService", + "localStorageService", + "$timeout", + function ($resource, envService, localStorageService, $timeout) { + let Spec; + if (envService.is("production")) { + Spec = $resource( + "/api/spec/:id", + {}, + { + update: { + method: "PUT", + }, + } + ); + } else { + // not on a production environment, return mocked Spec with localStorage + Spec = { + query: function (params, callback) { + console.log("localstorage query"); + $timeout(function () { + // simulate async so the callback works + var specs = []; + var lsKeys = localStorageService.keys(); + lsKeys.forEach(function (lsKey) { + var spec = localStorageService.get(lsKey); + var flat = { + group: spec.groupHandle, // match on groupHandle + id: spec.id, + owner: spec.permissions.owner, + privacy: spec.permissions.privacy, + timestamp: (Date.now() / 1000) | 0, + title: spec.title, + }; + var isMatch = Object.keys(params).every(function (paramKey) { + return flat[paramKey] == params[paramKey]; + }); + if (isMatch) { + flat.group = spec.group; // return group name + specs.push(flat); + } + }); + callback(specs); + }, 0); + }, + get: function (params, callback) { + console.log("localstorage get"); + $timeout(function () { + // simulate async so the callback works + var data = localStorageService.get(params.id); + callback(data); + }, 0); + }, + save: function (value, callback) { + console.log("localstorage save"); + $timeout(function () { + // simulate async so the callback works + var id = Math.round(Math.random() * 100000000); + while (localStorageService.get(id)) + id = Math.round(Math.random() * 100000000); + + value.id = id; + localStorageService.set(id, value); + callback({ id: id }); + }, 0); + }, + update: function (params, value, callback) { + $timeout(function () { + // simulate async so the callback works + console.log("localstorage update"); + localStorageService.set(params.id, value); + callback(value); + }, 0); + }, + delete: function (params, callback) { + console.log("localstorage delete"); + $timeout(function () { + // simulate async so the callback works + localStorageService.remove(params.id); + callback({}); + }, 0); + }, + }; + } + + return Spec; + }, + ]; + return this.$get; +}); diff --git a/app/js/specTabCtrl.js b/app/js/specTabCtrl.js deleted file mode 100755 index 56c57a8..0000000 --- a/app/js/specTabCtrl.js +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -app.controller('specTabCtrl', function ($scope, $location, $filter, $sce, Spec, storageService) { - // Initial Config - $scope.canEdit = false; - $scope.editing = false; - $scope.overlay = false; - $scope.configuring = false; - $scope.showingVideoWarning = false; - $scope.canScrubVideo = false; - $scope.showingCode = false; - - $scope.addingRow = null; - $scope.selectedRow = null; - $scope.resizingRow = null; - - $scope.getVideoSrc = function (src) { - var URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/; - var ID_REGEX = /[-\w]{25,}/g; - - if (src && src.search(ID_REGEX) != -1) { - var videoId = src.match(ID_REGEX); - console.log('> Video is a Drive ID or Drive URL'); - // Is a drive ID - return $sce.trustAsResourceUrl('https://docs.google.com/uc?authuser=0&id=' + videoId + '&export=download'); - } else if (src && src.search(URL_REGEX) != -1) { - console.log('> Video is a full URL'); - // Is a full URL - return $sce.trustAsResourceUrl(src); - } else { - // Something went wrong - console.log('Something went wrong trying to load the video'); - } - } - - $scope.$watch('spec.videoUrl', function () { - if ($scope.spec) { - $scope.spec.videoSrc = $scope.getVideoSrc($scope.spec.videoUrl); - } - }); - - var recalculate = function () { - if ($scope.spec) { - var msPerFrame = 1000 / $scope.spec.fps; - - $scope.spec.duration = $scope.spec.frames * msPerFrame; - - $scope.spec.divisions.minor = msPerFrame * $scope.spec.divisions.minorFrames; - $scope.spec.divisions.major = msPerFrame * $scope.spec.divisions.majorFrames; - - if ($scope.spec.exactTiming) { - $scope.decimalPlaces = 2; - } else { - $scope.decimalPlaces = 0; - } - - $scope.createLabels(); - } - } - - $scope.$watchGroup([ - 'spec.exactTiming', - 'spec.fps', - 'spec.frames', - 'spec.divisions.minorFrames', - 'spec.divisions.majorFrames'], function () { - recalculate(); - }); - - // Autosave - storageService.autosave($scope); - - // Initial Data Setup - if ($scope.specId) { - Spec.get({id: $scope.specId}, function (data) { - // TODO: Handle failure - - console.log(data); - $scope.data = data; - $scope.spec = $scope.data.spec; - - // check if can edit - if ($scope.data.permissions.owner === $scope.user) { - $scope.canEdit = true; - } - - // Loop through all rows and set the easing option again - for (var i = 0; i < $scope.spec.rows.length; i++) { - var row = $scope.spec.rows[i]; - // Set easing. - var easing = matchOption( - $scope.easingOptions, - row.easing, - { label: 'Linear', value: 'linear' } - ); - row.easing = easing; - // Set tag. - var tag = matchOption( - $scope.tagOptions, - row.tag, - { label: 'None', value: 'none' } - ); - row.tag = tag; - }; - }); - // Check if should be editing. - if ($location.search().create == 'true') { - $scope.editing = true; - $scope.configuring = true; - $scope.overlay = true; - } - $location.search(''); - } else { - $scope.data = { - group: null, - groupHandle: null, - title: null, - permissions: { - privacy: 'public', - owner: $scope.user, - editors: [], - viewers: [] - }, - spec: { - title: null, - videoUrl: null, - duration: 500, - frames: 30, - fps: 60, - exactTiming: false, - canvas: { - width: 0 - }, - divisions: { - minor: 15, // ms - minorFrames: 1, - major: 75, // ms - majorFrames: 5, - minorCount: null, - majorCount: null, - minorGap: null, - majorGap: null - }, - rows: [] - } - }; - - $scope.spec = $scope.data.spec; - - // Start with editing mode on a new spec - $scope.editing = true; - } - - // Watch group name to make sure a handle is generated - $scope.$watch('data.group', function () { - if ($scope.data && $scope.data.group) { - var handle = $scope.data.group.replace(/\s+/g, '-'); - $scope.data.groupHandle = handle.toLowerCase(); - console.log('> New Group Handle: ' + $scope.data.groupHandle); - } - }); - - // keep sidebar up to date - $scope.$watchGroup(['data.group', 'data.title'], function() { - $scope.refreshSidebar(); - }); - - // Changing Config - $scope.editSpec = function () { - if ($scope.canEdit) { - $scope.editing = true; - } - $scope.refreshCanvas(); - } - - $scope.previewSpec = function () { - if ($scope.canEdit) { - $scope.editing = false; - } - if ($scope.configuring) { - $scope.toggleConfig(); - } - if ($scope.addingRow) { - $scope.addingRow = null; - } - $scope.refreshCanvas(); - $location.search(''); - } - - $scope.toggleConfig = function () { - $scope.configuring = !$scope.configuring; - $scope.overlay = $scope.configuring; - } - - $scope.toggleVideo = function () { - if ($scope.editing) { - // Add a video URL with Google Drive picker - loadPicker($scope); - } - } - - $scope.toggleVideoWarning = function(show) { - if (typeof show === "undefined") { - $scope.showingVideoWarning = !$scope.showingVideoWarning; - } - else { - $scope.showingVideoWarning = show; - } - } - - $scope.setCanScrubVideo = function(canScrub) { - $scope.canScrubVideo = canScrub; - } - - $scope.toggleCodePopup = function () { - $scope.showingCode = !$scope.showingCode; - $scope.overlay = $scope.showingCode; - } - - $scope.closeOverlay = function () { - // Turn off settings popup - if ($scope.configuring) { - $scope.toggleConfig(); - } - // Turn off easing details - if ($scope.showingCode) { - $scope.toggleCodePopup(); - } - }; - - var matchOption = function (easingOrTagOptions, option, unmatchedOption) { - if (option) { - for (var i = 0; i < easingOrTagOptions.length; i++) { - var opt = easingOrTagOptions[i]; - if (opt.value === option.value) { - return opt; - } - } - } - // Not set, therefore return none. - return unmatchedOption; - }; - - // Special case for first row adding - $scope.firstRow = { - adding: false - } - - // Grid Labels - $scope.labels = { - frames: [], - ms: [] - }; - - $scope.createLabels = function () { - $scope.labels.frames.length = 0; - $scope.labels.ms.length = 0; - - // Calculate frame labels - if ($scope.spec && $scope.spec.divisions.majorCount) { - for (var i = 0; i <= $scope.spec.divisions.majorCount; i++) { - var num = i * $scope.spec.divisions.majorFrames; - var label = num; - - if (i === 0) { - label = 'Frames' - } - - $scope.labels.frames.push(label); - } - } - - // Calculate ms labels - if ($scope.spec && $scope.spec.divisions.majorCount) { - for (var i = 0; i <= $scope.spec.divisions.majorCount; i++) { - var num = i * $scope.spec.divisions.major; - var label = num; - - if (i === 0) { - label = 'Ms' - } else { - label = $filter('number')(label, $scope.decimalPlaces); - } - - $scope.labels.ms.push(label); - } - } - } - - // Watch for grid computations - $scope.$watch('spec.divisions.majorCount', function () { - $scope.createLabels(); - }); - - // Toggle drawer - $scope.toggleDrawer = function (row, isOpen) { - if ($scope.addingRow) { - // clear adding row - $scope.addingRow = null; - } - if (row && ($scope.selectedRow != row || isOpen)) { - // show drawer - $scope.selectedRow = row; - } - else { - // hide drawer - $scope.selectedRow = null; - } - $scope.refreshCanvas(); - } - - // Toggle row adder - $scope.toggleNewRow = function (row, isOpen) { - if ($scope.selectedRow) { - // clear selected row - $scope.selectedRow = null; - } - if (row && ($scope.addingRow != row || isOpen)) { - // show new row - $scope.addingRow = row; - } - else { - // hide new row - $scope.addingRow = null; - } - $scope.refreshCanvas(); - } - - // Set resizing row - $scope.setResizingRow = function(row) { - $scope.resizingRow = row; - } - - // Refresh on duration / division change - $scope.$watchGroup(['spec.duration', 'spec.divisions'], function (newValues, oldValues, scope) { - $scope.refreshCanvas(); - }); - - // Change Color - $scope.changeColor = function (row, color) { - row.color = color; - } - - // Delete A Row - $scope.deleteRow = function (row) { - var index = $scope.spec.rows.indexOf(row); - - if (index > -1) { - $scope.spec.rows.splice(index, 1); - $scope.refreshCanvas(); - } - } - -}); diff --git a/app/js/specTabCtrl.ts b/app/js/specTabCtrl.ts new file mode 100755 index 0000000..2b7f7a9 --- /dev/null +++ b/app/js/specTabCtrl.ts @@ -0,0 +1,377 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +app.controller( + "specTabCtrl", + function ($scope, $location, $filter, $sce, Spec, storageService) { + // Initial Config + $scope.canEdit = false; + $scope.editing = false; + $scope.overlay = false; + $scope.configuring = false; + $scope.showingVideoWarning = false; + $scope.canScrubVideo = false; + $scope.showingCode = false; + + $scope.addingRow = null; + $scope.selectedRow = null; + $scope.resizingRow = null; + + $scope.getVideoSrc = function (src) { + var URL_REGEX = + /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/; + var ID_REGEX = /[-\w]{25,}/g; + + if (src && src.search(ID_REGEX) != -1) { + var videoId = src.match(ID_REGEX); + console.log("> Video is a Drive ID or Drive URL"); + // Is a drive ID + return $sce.trustAsResourceUrl( + "https://docs.google.com/uc?authuser=0&id=" + + videoId + + "&export=download" + ); + } else if (src && src.search(URL_REGEX) != -1) { + console.log("> Video is a full URL"); + // Is a full URL + return $sce.trustAsResourceUrl(src); + } else { + // Something went wrong + console.log("Something went wrong trying to load the video"); + } + }; + + $scope.$watch("spec.videoUrl", function () { + if ($scope.spec) { + $scope.spec.videoSrc = $scope.getVideoSrc($scope.spec.videoUrl); + } + }); + + var recalculate = function () { + if ($scope.spec) { + var msPerFrame = 1000 / $scope.spec.fps; + + $scope.spec.duration = $scope.spec.frames * msPerFrame; + + $scope.spec.divisions.minor = + msPerFrame * $scope.spec.divisions.minorFrames; + $scope.spec.divisions.major = + msPerFrame * $scope.spec.divisions.majorFrames; + + if ($scope.spec.exactTiming) { + $scope.decimalPlaces = 2; + } else { + $scope.decimalPlaces = 0; + } + + $scope.createLabels(); + } + }; + + $scope.$watchGroup( + [ + "spec.exactTiming", + "spec.fps", + "spec.frames", + "spec.divisions.minorFrames", + "spec.divisions.majorFrames", + ], + function () { + recalculate(); + } + ); + + // Autosave + storageService.autosave($scope); + + // Initial Data Setup + if ($scope.specId) { + Spec.get({ id: $scope.specId }, function (data) { + // TODO: Handle failure + + console.log(data); + $scope.data = data; + $scope.spec = $scope.data.spec; + + // check if can edit + if ($scope.data.permissions.owner === $scope.user) { + $scope.canEdit = true; + } + + // Loop through all rows and set the easing option again + for (var i = 0; i < $scope.spec.rows.length; i++) { + var row = $scope.spec.rows[i]; + // Set easing. + var easing = matchOption($scope.easingOptions, row.easing, { + label: "Linear", + value: "linear", + }); + row.easing = easing; + // Set tag. + var tag = matchOption($scope.tagOptions, row.tag, { + label: "None", + value: "none", + }); + row.tag = tag; + } + }); + // Check if should be editing. + if ($location.search().create == "true") { + $scope.editing = true; + $scope.configuring = true; + $scope.overlay = true; + } + $location.search(""); + } else { + $scope.data = { + group: null, + groupHandle: null, + title: null, + permissions: { + privacy: "public", + owner: $scope.user, + editors: [], + viewers: [], + }, + spec: { + title: null, + videoUrl: null, + duration: 500, + frames: 30, + fps: 60, + exactTiming: false, + canvas: { + width: 0, + }, + divisions: { + minor: 15, // ms + minorFrames: 1, + major: 75, // ms + majorFrames: 5, + minorCount: null, + majorCount: null, + minorGap: null, + majorGap: null, + }, + rows: [], + }, + }; + + $scope.spec = $scope.data.spec; + + // Start with editing mode on a new spec + $scope.editing = true; + } + + // Watch group name to make sure a handle is generated + $scope.$watch("data.group", function () { + if ($scope.data && $scope.data.group) { + var handle = $scope.data.group.replace(/\s+/g, "-"); + $scope.data.groupHandle = handle.toLowerCase(); + console.log("> New Group Handle: " + $scope.data.groupHandle); + } + }); + + // keep sidebar up to date + $scope.$watchGroup(["data.group", "data.title"], function () { + $scope.refreshSidebar(); + }); + + // Changing Config + $scope.editSpec = function () { + if ($scope.canEdit) { + $scope.editing = true; + } + $scope.refreshCanvas(); + }; + + $scope.previewSpec = function () { + if ($scope.canEdit) { + $scope.editing = false; + } + if ($scope.configuring) { + $scope.toggleConfig(); + } + if ($scope.addingRow) { + $scope.addingRow = null; + } + $scope.refreshCanvas(); + $location.search(""); + }; + + $scope.toggleConfig = function () { + $scope.configuring = !$scope.configuring; + $scope.overlay = $scope.configuring; + }; + + $scope.toggleVideo = function () { + if ($scope.editing) { + // Add a video URL with Google Drive picker + loadPicker($scope); + } + }; + + $scope.toggleVideoWarning = function (show) { + if (typeof show === "undefined") { + $scope.showingVideoWarning = !$scope.showingVideoWarning; + } else { + $scope.showingVideoWarning = show; + } + }; + + $scope.setCanScrubVideo = function (canScrub) { + $scope.canScrubVideo = canScrub; + }; + + $scope.toggleCodePopup = function () { + $scope.showingCode = !$scope.showingCode; + $scope.overlay = $scope.showingCode; + }; + + $scope.closeOverlay = function () { + // Turn off settings popup + if ($scope.configuring) { + $scope.toggleConfig(); + } + // Turn off easing details + if ($scope.showingCode) { + $scope.toggleCodePopup(); + } + }; + + var matchOption = function (easingOrTagOptions, option, unmatchedOption) { + if (option) { + for (var i = 0; i < easingOrTagOptions.length; i++) { + var opt = easingOrTagOptions[i]; + if (opt.value === option.value) { + return opt; + } + } + } + // Not set, therefore return none. + return unmatchedOption; + }; + + // Special case for first row adding + $scope.firstRow = { + adding: false, + }; + + // Grid Labels + $scope.labels = { + frames: [], + ms: [], + }; + + $scope.createLabels = function () { + $scope.labels.frames.length = 0; + $scope.labels.ms.length = 0; + + // Calculate frame labels + if ($scope.spec && $scope.spec.divisions.majorCount) { + for (var i = 0; i <= $scope.spec.divisions.majorCount; i++) { + var num = i * $scope.spec.divisions.majorFrames; + let label = num.toString(); + + if (i === 0) { + label = "Frames"; + } + + $scope.labels.frames.push(label); + } + } + + // Calculate ms labels + if ($scope.spec && $scope.spec.divisions.majorCount) { + for (var i = 0; i <= $scope.spec.divisions.majorCount; i++) { + var num = i * $scope.spec.divisions.major; + let label: string = num.toString(); + + if (i === 0) { + label = "Ms"; + } else { + label = $filter("number")(label, $scope.decimalPlaces); + } + + $scope.labels.ms.push(label); + } + } + }; + + // Watch for grid computations + $scope.$watch("spec.divisions.majorCount", function () { + $scope.createLabels(); + }); + + // Toggle drawer + $scope.toggleDrawer = function (row, isOpen) { + if ($scope.addingRow) { + // clear adding row + $scope.addingRow = null; + } + if (row && ($scope.selectedRow != row || isOpen)) { + // show drawer + $scope.selectedRow = row; + } else { + // hide drawer + $scope.selectedRow = null; + } + $scope.refreshCanvas(); + }; + + // Toggle row adder + $scope.toggleNewRow = function (row, isOpen) { + if ($scope.selectedRow) { + // clear selected row + $scope.selectedRow = null; + } + if (row && ($scope.addingRow != row || isOpen)) { + // show new row + $scope.addingRow = row; + } else { + // hide new row + $scope.addingRow = null; + } + $scope.refreshCanvas(); + }; + + // Set resizing row + $scope.setResizingRow = function (row) { + $scope.resizingRow = row; + }; + + // Refresh on duration / division change + $scope.$watchGroup( + ["spec.duration", "spec.divisions"], + function (newValues, oldValues, scope) { + $scope.refreshCanvas(); + } + ); + + // Change Color + $scope.changeColor = function (row, color) { + row.color = color; + }; + + // Delete A Row + $scope.deleteRow = function (row) { + var index = $scope.spec.rows.indexOf(row); + + if (index > -1) { + $scope.spec.rows.splice(index, 1); + $scope.refreshCanvas(); + } + }; + } +); diff --git a/app/js/storageService.js b/app/js/storageService.js deleted file mode 100644 index 49a8e83..0000000 --- a/app/js/storageService.js +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -app.service('storageService', function storageService($timeout, $location, Spec) { - - var saveFinished = function(scope) { - // Set minimum time to prevent progress bar from disappearing too quickly. - $timeout(function() { - scope.uiState.saveInProgress = false; - }, 150); - // Remove navigation prompt - window.onbeforeunload = null; - }; - - // called when scope.data changes - var onDataChanged = function (newVal, oldVal, scope) { - if (shouldSave(newVal, oldVal, scope)) { - scope.uiState.saveInProgress = true; - // Enable navigation prompt - window.onbeforeunload = function() { - return true; - }; - save(scope); - } - }; - - // Remove stateful UI properties - var sanitizedData = function (data) { - if (typeof data === 'undefined') return data; - // Clone data - var sanitizedData = JSON.parse(JSON.stringify(data)); - - // spec properties to remove - delete sanitizedData.spec.canvas.width; - delete sanitizedData.spec.divisions.minorCount; - delete sanitizedData.spec.divisions.minorGap; - delete sanitizedData.spec.divisions.majorCount; - delete sanitizedData.spec.divisions.majorGap; - - return sanitizedData; - } - - var autosave = function(scope) { - scope.uiState.saveInProgress = false; - scope.$watch('data', onDataChanged, true); - scope.$watch('data.id', function(newVal, oldVal, scope) { - if (scope.data && !scope.data.id) { - create(scope); - } - }, true); - } - - // saves to database (debounced to 1 per second) - var save = (function (scope) { - // Update Spec - Spec.update({ id: scope.data.id }, sanitizedData(scope.data), function (resp) { - console.log(resp); - saveFinished(scope); - }, function(error) { - saveFinished(scope); - }); - }).debounce(1000); - - var create = function(scope) { - // Create Spec - Spec.save(sanitizedData(scope.data), function (resp) { - console.log(resp); - // Redirect to correct URL - $location.path('/spec/' + resp.id); - $location.search('create', 'true'); - saveFinished(scope); - }, function(error) { - saveFinished(scope); - }); - } - - // check if properties, excluding stateful UI properties, have changed - var shouldSave = function(newVal, oldVal, scope) { - newVal = sanitizedData(newVal); - oldVal = sanitizedData(oldVal); - - // use angular.equals to compare ignoring angular $ properties - return oldVal && (scope.addingRow || !angular.equals(newVal, oldVal)); - } - - return { - autosave: autosave - } -}); diff --git a/app/js/storageService.ts b/app/js/storageService.ts new file mode 100644 index 0000000..9d56d80 --- /dev/null +++ b/app/js/storageService.ts @@ -0,0 +1,117 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +app.service( + "storageService", + function storageService($timeout, $location, Spec) { + var saveFinished = function (scope) { + // Set minimum time to prevent progress bar from disappearing too quickly. + $timeout(function () { + scope.uiState.saveInProgress = false; + }, 150); + // Remove navigation prompt + window.onbeforeunload = null; + }; + + // called when scope.data changes + var onDataChanged = function (newVal, oldVal, scope) { + if (shouldSave(newVal, oldVal, scope)) { + scope.uiState.saveInProgress = true; + // Enable navigation prompt + window.onbeforeunload = function () { + return true; + }; + save(scope); + } + }; + + // Remove stateful UI properties + var sanitizedData = function (data) { + if (typeof data === "undefined") return data; + // Clone data + var sanitizedData = JSON.parse(JSON.stringify(data)); + + // spec properties to remove + delete sanitizedData.spec.canvas.width; + delete sanitizedData.spec.divisions.minorCount; + delete sanitizedData.spec.divisions.minorGap; + delete sanitizedData.spec.divisions.majorCount; + delete sanitizedData.spec.divisions.majorGap; + + return sanitizedData; + }; + + var autosave = function (scope) { + scope.uiState.saveInProgress = false; + scope.$watch("data", onDataChanged, true); + scope.$watch( + "data.id", + function (newVal, oldVal, scope) { + if (scope.data && !scope.data.id) { + create(scope); + } + }, + true + ); + }; + + // saves to database (debounced to 1 per second) + var save = function (scope) { + // Update Spec + Spec.update( + { id: scope.data.id }, + sanitizedData(scope.data), + function (resp) { + console.log(resp); + saveFinished(scope); + }, + function (error) { + saveFinished(scope); + } + ); + } + // @ts-ignore + .debounce(1000); + + var create = function (scope) { + // Create Spec + Spec.save( + sanitizedData(scope.data), + function (resp) { + console.log(resp); + // Redirect to correct URL + $location.path("/spec/" + resp.id); + $location.search("create", "true"); + saveFinished(scope); + }, + function (error) { + saveFinished(scope); + } + ); + }; + + // check if properties, excluding stateful UI properties, have changed + var shouldSave = function (newVal, oldVal, scope) { + newVal = sanitizedData(newVal); + oldVal = sanitizedData(oldVal); + + // use angular.equals to compare ignoring angular $ properties + return oldVal && (scope.addingRow || !angular.equals(newVal, oldVal)); + }; + + return { + autosave: autosave, + }; + } +); diff --git a/app/js/userCtrl.js b/app/js/userCtrl.js deleted file mode 100755 index fd05245..0000000 --- a/app/js/userCtrl.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -app.controller('userCtrl', function ( - $scope, - $routeParams, - Spec, - projectListService) { - - // Config - $scope.hasProjects = true; - $scope.projectGroups = []; - $scope.selected = []; - - // Check if the current user is the owner - if ($routeParams.user === $scope.user) { - $scope.isOwner = true; - } else { - $scope.isOwner = false; - } - - Spec.query({owner: $routeParams.user}, function (specs) { - // Show new project message if necessary - if (specs.length < 1) { - $scope.hasProjects = false; - } - - angular.forEach(specs, function (spec, index) { - projectListService.addProject($scope, spec); - }); - }); - - $scope.toggleSelected = function(item) { - projectListService.toggleSelected($scope, item); - }; - - $scope.isSelected = function(item) { - return projectListService.isSelected($scope, item); - }; - - $scope.selectedToRouteParam = function() { - return projectListService.selectedToRouteParam($scope); - } - - $scope.deleteProject = function(ev, project) { - $scope.$parent.deleteProject(ev, project, function() { - projectListService.deleteProject($scope, project); - }); - } -}); diff --git a/app/js/userCtrl.ts b/app/js/userCtrl.ts new file mode 100755 index 0000000..1a69dbe --- /dev/null +++ b/app/js/userCtrl.ts @@ -0,0 +1,59 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +app.controller( + "userCtrl", + function ($scope, $routeParams, Spec, projectListService) { + // Config + $scope.hasProjects = true; + $scope.projectGroups = []; + $scope.selected = []; + + // Check if the current user is the owner + if ($routeParams.user === $scope.user) { + $scope.isOwner = true; + } else { + $scope.isOwner = false; + } + + Spec.query({ owner: $routeParams.user }, function (specs) { + // Show new project message if necessary + if (specs.length < 1) { + $scope.hasProjects = false; + } + + angular.forEach(specs, function (spec, index) { + projectListService.addProject($scope, spec); + }); + }); + + $scope.toggleSelected = function (item) { + projectListService.toggleSelected($scope, item); + }; + + $scope.isSelected = function (item) { + return projectListService.isSelected($scope, item); + }; + + $scope.selectedToRouteParam = function () { + return projectListService.selectedToRouteParam($scope); + }; + + $scope.deleteProject = function (ev, project) { + $scope.$parent.deleteProject(ev, project, function () { + projectListService.deleteProject($scope, project); + }); + }; + } +); diff --git a/bower.json b/bower.json index cfbb0e1..4c1c37c 100755 --- a/bower.json +++ b/bower.json @@ -1,5 +1,5 @@ { - "name": "Direct", + "name": "direct", "version": "0.10.0", "description": "Motion Specification Tool", "private": true, diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c55e26d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,71 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "include": ["bower_components", "node_modules"] +} From 7f6865fa8adf9ed17b751673a58a6712be4f09a1 Mon Sep 17 00:00:00 2001 From: Rody Davis Date: Tue, 15 Jun 2021 16:25:10 -0700 Subject: [PATCH 02/17] generating js --- .gitignore | 2 +- app/js/app.ts | 4 ++++ app/js/gapi.ts | 3 --- bower.json | 2 +- tsconfig.json | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 290da7d..818cbe1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ bower_components *.pyc .DS_Store - +app/js/*.js config.js config.yaml diff --git a/app/js/app.ts b/app/js/app.ts index 5e27f3f..df1001a 100755 --- a/app/js/app.ts +++ b/app/js/app.ts @@ -20,6 +20,10 @@ if (window) { Object.assign(config, window.__directConfig); } +declare const gapi; +declare const google; +declare const angular; + const app = angular.module("spec", [ "ngRoute", "ngResource", diff --git a/app/js/gapi.ts b/app/js/gapi.ts index aa58371..382536c 100644 --- a/app/js/gapi.ts +++ b/app/js/gapi.ts @@ -26,9 +26,6 @@ var pickerApiLoaded = false; var oauthToken; var scopeModel; -declare const gapi; -declare const google; - function onApiLoad() { gapi.load("auth"); gapi.load("picker", { callback: onPickerApiLoad }); diff --git a/bower.json b/bower.json index 4c1c37c..e38b134 100755 --- a/bower.json +++ b/bower.json @@ -29,4 +29,4 @@ "resolutions": { "jquery": ">=3.1.x" } -} +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index c55e26d..733ac10 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,7 +25,7 @@ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ - "strict": true /* Enable all strict type-checking options. */, + "strict": false /* Enable all strict type-checking options. */, // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ @@ -67,5 +67,5 @@ "skipLibCheck": true /* Skip type checking of declaration files. */, "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, - "include": ["bower_components", "node_modules"] + "include": ["bower_components", "node_modules", "app/js/**/*.ts"] } From 9fdb35ec8a3f48490e6bc178e8a097e238987b23 Mon Sep 17 00:00:00 2001 From: Rody Davis Date: Tue, 15 Jun 2021 16:31:50 -0700 Subject: [PATCH 03/17] Update specResource.ts --- app/js/specResource.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/js/specResource.ts b/app/js/specResource.ts index df76e6b..a6ca2bc 100755 --- a/app/js/specResource.ts +++ b/app/js/specResource.ts @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// @ts-nocheck + app.provider("Spec", function () { this.$get = [ "$resource", @@ -19,9 +21,8 @@ app.provider("Spec", function () { "localStorageService", "$timeout", function ($resource, envService, localStorageService, $timeout) { - let Spec; if (envService.is("production")) { - Spec = $resource( + var Spec = $resource( "/api/spec/:id", {}, { @@ -32,7 +33,7 @@ app.provider("Spec", function () { ); } else { // not on a production environment, return mocked Spec with localStorage - Spec = { + var Spec = { query: function (params, callback) { console.log("localstorage query"); $timeout(function () { @@ -103,5 +104,4 @@ app.provider("Spec", function () { return Spec; }, ]; - return this.$get; }); From 8d161749062719dfb347604abf4ca933a52bf797 Mon Sep 17 00:00:00 2001 From: Rody Davis Date: Tue, 15 Jun 2021 16:50:53 -0700 Subject: [PATCH 04/17] migrating from bower --- .gitignore | 1 + bower.json | 32 --------------------- package-lock.json | 73 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 46 +++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 32 deletions(-) delete mode 100755 bower.json create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore index 818cbe1..2eda8a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ bower_components +node_modules *.pyc .DS_Store diff --git a/bower.json b/bower.json deleted file mode 100755 index e38b134..0000000 --- a/bower.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "direct", - "version": "0.10.0", - "description": "Motion Specification Tool", - "private": true, - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ], - "dependencies": { - "angular": "~1.4.5", - "angular-animate": "~1.4.5", - "angular-aria": "~1.4.5", - "angular-material": "~0.11.0", - "angular-resource": "~1.4.5", - "angular-route": "~1.4.5", - "angularytics": "0.3.0", - "hammerjs": "~2.0.4", - "hidpi-canvas": "1.0.9", - "jquery": "2.1.1", - "angular-environment": "^1.0.8", - "angular-local-storage": "^0.7.1", - "angular-ui-sortable": "^0.17.1", - "js-throttle-debounce": "^0.1.1" - }, - "resolutions": { - "jquery": ">=3.1.x" - } -} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..fca5869 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,73 @@ +{ + "name": "direct", + "version": "0.10.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "angular": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/angular/-/angular-1.4.14.tgz", + "integrity": "sha1-nQ/q9gzm5SzlD0nuMoZW0eGHXDc=" + }, + "angular-animate": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.4.14.tgz", + "integrity": "sha1-7kBoyv234jACYxnsbLkgesqJgDg=" + }, + "angular-aria": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/angular-aria/-/angular-aria-1.4.14.tgz", + "integrity": "sha1-TIFXGByfZwcxTRXHwqnLy7HrY54=" + }, + "angular-environment": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/angular-environment/-/angular-environment-1.0.8.tgz", + "integrity": "sha1-yBheuHY+bvCHeroZsnMGmdG5UlE=" + }, + "angular-local-storage": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/angular-local-storage/-/angular-local-storage-0.7.1.tgz", + "integrity": "sha1-+9JzB2PCn6mvVyXgGGx4BiHozdI=" + }, + "angular-material": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/angular-material/-/angular-material-0.11.4.tgz", + "integrity": "sha1-Z+p3KxMKzoyAsCuB10uANRuRl20=" + }, + "angular-resource": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/angular-resource/-/angular-resource-1.4.14.tgz", + "integrity": "sha1-OCpITi3OJb+7U1g+eD+D5dxb7mQ=" + }, + "angular-route": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/angular-route/-/angular-route-1.4.14.tgz", + "integrity": "sha1-Ll2/4SOUI8Z4Flw5uzhgGtZqB5Q=" + }, + "angular-ui-sortable": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/angular-ui-sortable/-/angular-ui-sortable-0.17.2.tgz", + "integrity": "sha1-jEQmytMGx83RwwtFSvhbLRWBjNw=" + }, + "angularytics": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/angularytics/-/angularytics-0.3.0.tgz", + "integrity": "sha1-7h/aR5mDU2LzyrjLTFabhIArpAY=" + }, + "hammerjs": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", + "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" + }, + "jquery": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", + "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" + }, + "js-throttle-debounce": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/js-throttle-debounce/-/js-throttle-debounce-0.1.1.tgz", + "integrity": "sha1-tEhMeDuMPspO/gr4dearuZs1g2Q=" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6443a19 --- /dev/null +++ b/package.json @@ -0,0 +1,46 @@ +{ + "name": "direct", + "version": "0.10.0", + "description": "Direct is a tool that helps motion designers provide clear, precise motion direction for engineers.", + "private": true, + "main": "index.js", + "scripts": { + "serve": "tsc && sudo dev_appserver.py .", + "setup": "bower install" + }, + "dependencies": { + "angular": "~1.4.5", + "angular-animate": "~1.4.5", + "angular-aria": "~1.4.5", + "angular-material": "~0.11.0", + "angular-resource": "~1.4.5", + "angular-route": "~1.4.5", + "angularytics": "0.3.0", + "hammerjs": "~2.0.4", + "jquery": "^3.1.1", + "angular-environment": "^1.0.8", + "angular-local-storage": "^0.7.1", + "angular-ui-sortable": "^0.17.1", + "js-throttle-debounce": "^0.1.1" + }, + "devDependencies": { + "bower": "^1.8.0", + "json-server": "^0.9.6", + "rimraf": "^2.6.2", + "serve": "^5.1.2", + "ts-loader": "^3.2.0", + "typescript": "^2.6.2", + "webpack": "^3.10.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/rodydavis/direct.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/rodydavis/direct/issues" + }, + "homepage": "https://github.com/rodydavis/direct#readme" +} \ No newline at end of file From d03bd632a040b93d621cd755fe6e4f822880e686 Mon Sep 17 00:00:00 2001 From: Rody Davis Date: Tue, 15 Jun 2021 17:18:08 -0700 Subject: [PATCH 05/17] moving to npm --- .bowerrc | 3 - app.yaml | 77 +- package-lock.json | 5 + package.json | 5 +- templates/index.html | 116 +- third_party/angular-ui-sortable/.bower.json | 22 + third_party/angular-ui-sortable/.travis.yml | 5 + third_party/angular-ui-sortable/bower.json | 10 + third_party/angular-ui-sortable/sortable.js | 567 + .../angular-ui-sortable/sortable.min.js | 8 + third_party/jquery-ui/.bower.json | 22 + third_party/jquery-ui/.gitignore | 4 + third_party/jquery-ui/README.md | 12 + third_party/jquery-ui/bower.json | 13 + third_party/jquery-ui/component.json | 13 + third_party/jquery-ui/composer.json | 69 + third_party/jquery-ui/jquery-ui.js | 18706 ++++++++++++++++ third_party/jquery-ui/jquery-ui.min.js | 13 + third_party/jquery-ui/package.json | 16 + .../jquery-ui/themes/base/accordion.css | 23 + third_party/jquery-ui/themes/base/all.css | 12 + .../jquery-ui/themes/base/autocomplete.css | 16 + third_party/jquery-ui/themes/base/base.css | 30 + third_party/jquery-ui/themes/base/button.css | 82 + .../jquery-ui/themes/base/checkboxradio.css | 34 + .../jquery-ui/themes/base/controlgroup.css | 65 + third_party/jquery-ui/themes/base/core.css | 97 + .../jquery-ui/themes/base/datepicker.css | 185 + third_party/jquery-ui/themes/base/dialog.css | 101 + .../jquery-ui/themes/base/draggable.css | 12 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 86 bytes .../base/images/ui-icons_444444_256x240.png | Bin 0 -> 7090 bytes .../base/images/ui-icons_555555_256x240.png | Bin 0 -> 7074 bytes .../base/images/ui-icons_777620_256x240.png | Bin 0 -> 4676 bytes .../base/images/ui-icons_777777_256x240.png | Bin 0 -> 7111 bytes .../base/images/ui-icons_cc0000_256x240.png | Bin 0 -> 4676 bytes .../base/images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/base/jquery-ui.css | 1311 ++ .../jquery-ui/themes/base/jquery-ui.min.css | 7 + third_party/jquery-ui/themes/base/menu.css | 64 + .../jquery-ui/themes/base/progressbar.css | 28 + .../jquery-ui/themes/base/resizable.css | 78 + .../jquery-ui/themes/base/selectable.css | 17 + .../jquery-ui/themes/base/selectmenu.css | 50 + third_party/jquery-ui/themes/base/slider.css | 75 + .../jquery-ui/themes/base/sortable.css | 12 + third_party/jquery-ui/themes/base/spinner.css | 52 + third_party/jquery-ui/themes/base/tabs.css | 51 + third_party/jquery-ui/themes/base/theme.css | 443 + third_party/jquery-ui/themes/base/tooltip.css | 19 + .../ui-bg_diagonals-thick_8_333333_40x40.png | Bin 0 -> 383 bytes .../images/ui-bg_glass_40_111111_1x400.png | Bin 0 -> 323 bytes .../images/ui-bg_glass_55_1c1c1c_1x400.png | Bin 0 -> 323 bytes .../ui-bg_highlight-hard_100_f9f9f9_1x100.png | Bin 0 -> 315 bytes .../ui-bg_highlight-hard_40_aaaaaa_1x100.png | Bin 0 -> 316 bytes .../ui-bg_highlight-soft_50_aaaaaa_1x100.png | Bin 0 -> 327 bytes .../ui-bg_inset-hard_45_cd0a0a_1x100.png | Bin 0 -> 382 bytes .../ui-bg_inset-hard_55_ffeb80_1x100.png | Bin 0 -> 367 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 7025 bytes .../images/ui-icons_4ca300_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_bbbbbb_256x240.png | Bin 0 -> 7092 bytes .../images/ui-icons_ededed_256x240.png | Bin 0 -> 7011 bytes .../images/ui-icons_ffcf29_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/black-tie/jquery-ui.css | 1311 ++ .../themes/black-tie/jquery-ui.min.css | 7 + .../jquery-ui/themes/black-tie/theme.css | 443 + .../ui-bg_diagonals-thick_75_f3d8d8_40x40.png | Bin 0 -> 471 bytes .../images/ui-bg_dots-small_65_a6a6a6_2x2.png | Bin 0 -> 266 bytes .../images/ui-bg_glass_55_fbf8ee_1x400.png | Bin 0 -> 398 bytes .../ui-bg_highlight-hard_100_eeeeee_1x100.png | Bin 0 -> 316 bytes .../ui-bg_highlight-hard_100_f6f6f6_1x100.png | Bin 0 -> 316 bytes .../ui-bg_highlight-soft_15_cc0000_1x100.png | Bin 0 -> 385 bytes .../images/ui-icons_004276_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_cc0000_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/blitzer/jquery-ui.css | 1311 ++ .../themes/blitzer/jquery-ui.min.css | 7 + .../jquery-ui/themes/blitzer/theme.css | 443 + .../ui-bg_diagonals-thick_90_eeeeee_40x40.png | Bin 0 -> 380 bytes .../images/ui-bg_glass_100_e4f1fb_1x400.png | Bin 0 -> 408 bytes .../images/ui-bg_glass_50_3baae3_1x400.png | Bin 0 -> 394 bytes .../images/ui-bg_glass_80_d7ebf9_1x400.png | Bin 0 -> 404 bytes .../ui-bg_highlight-hard_100_f2f5f7_1x100.png | Bin 0 -> 390 bytes .../ui-bg_highlight-hard_70_000000_1x100.png | Bin 0 -> 310 bytes .../ui-bg_highlight-soft_100_deedf7_1x100.png | Bin 0 -> 445 bytes .../ui-bg_highlight-soft_25_ffef8f_1x100.png | Bin 0 -> 367 bytes .../images/ui-icons_2694e8_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_3d80b3_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_72a7cf_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/cupertino/jquery-ui.css | 1311 ++ .../themes/cupertino/jquery-ui.min.css | 7 + .../jquery-ui/themes/cupertino/theme.css | 443 + .../images/ui-bg_glass_40_ffc73d_1x400.png | Bin 0 -> 374 bytes .../ui-bg_highlight-hard_20_0972a5_1x100.png | Bin 0 -> 381 bytes .../ui-bg_highlight-soft_33_003147_1x100.png | Bin 0 -> 401 bytes .../ui-bg_highlight-soft_35_222222_1x100.png | Bin 0 -> 342 bytes .../ui-bg_highlight-soft_44_444444_1x100.png | Bin 0 -> 328 bytes .../ui-bg_highlight-soft_80_eeeeee_1x100.png | Bin 0 -> 335 bytes .../images/ui-bg_loop_25_000000_21x21.png | Bin 0 -> 378 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 7025 bytes .../images/ui-icons_4b8e0b_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_a83300_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_cccccc_256x240.png | Bin 0 -> 7034 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/dark-hive/jquery-ui.css | 1311 ++ .../themes/dark-hive/jquery-ui.min.css | 7 + .../jquery-ui/themes/dark-hive/theme.css | 443 + .../ui-bg_diagonals-thick_15_0b3e6f_40x40.png | Bin 0 -> 482 bytes .../ui-bg_dots-medium_30_0b58a2_4x4.png | Bin 0 -> 295 bytes .../images/ui-bg_dots-small_20_333333_2x2.png | Bin 0 -> 266 bytes .../images/ui-bg_dots-small_30_a32d00_2x2.png | Bin 0 -> 276 bytes .../images/ui-bg_dots-small_40_00498f_2x2.png | Bin 0 -> 282 bytes .../ui-bg_gloss-wave_20_111111_500x100.png | Bin 0 -> 3990 bytes .../images/ui-icons_00498f_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_98d2fb_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_9ccdfc_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/dot-luv/jquery-ui.css | 1311 ++ .../themes/dot-luv/jquery-ui.min.css | 7 + .../jquery-ui/themes/dot-luv/theme.css | 443 + .../ui-bg_gloss-wave_30_3d3644_500x100.png | Bin 0 -> 5999 bytes .../ui-bg_highlight-soft_100_dcd9de_1x100.png | Bin 0 -> 400 bytes .../ui-bg_highlight-soft_100_eae6ea_1x100.png | Bin 0 -> 431 bytes .../ui-bg_highlight-soft_25_30273a_1x100.png | Bin 0 -> 420 bytes .../ui-bg_highlight-soft_45_5f5964_1x100.png | Bin 0 -> 405 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 7090 bytes .../images/ui-icons_734d99_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_8d78a5_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_a8a3ae_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ebccce_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/eggplant/jquery-ui.css | 1311 ++ .../themes/eggplant/jquery-ui.min.css | 7 + .../jquery-ui/themes/eggplant/theme.css | 443 + .../ui-bg_diagonals-small_25_c5ddfc_40x40.png | Bin 0 -> 400 bytes .../ui-bg_diagonals-thick_20_e69700_40x40.png | Bin 0 -> 475 bytes .../ui-bg_diagonals-thick_22_1484e6_40x40.png | Bin 0 -> 467 bytes .../ui-bg_diagonals-thick_26_2293f7_40x40.png | Bin 0 -> 464 bytes .../ui-bg_highlight-soft_100_f9f9f9_1x100.png | Bin 0 -> 325 bytes .../ui-bg_inset-hard_100_eeeeee_1x100.png | Bin 0 -> 314 bytes .../images/ui-icons_0a82eb_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_0b54d5_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_5fa5e3_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_fcdd4a_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../themes/excite-bike/jquery-ui.css | 1311 ++ .../themes/excite-bike/jquery-ui.min.css | 7 + .../jquery-ui/themes/excite-bike/theme.css | 443 + .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 265 bytes .../ui-bg_highlight-soft_100_f6f6f6_1x100.png | Bin 0 -> 330 bytes .../ui-bg_highlight-soft_25_0073ea_1x100.png | Bin 0 -> 393 bytes .../ui-bg_highlight-soft_50_dddddd_1x100.png | Bin 0 -> 339 bytes .../flick/images/ui-icons_0073ea_256x240.png | Bin 0 -> 4676 bytes .../flick/images/ui-icons_454545_256x240.png | Bin 0 -> 7090 bytes .../flick/images/ui-icons_666666_256x240.png | Bin 0 -> 7111 bytes .../flick/images/ui-icons_ff0084_256x240.png | Bin 0 -> 4676 bytes .../flick/images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/flick/jquery-ui.css | 1311 ++ .../jquery-ui/themes/flick/jquery-ui.min.css | 7 + third_party/jquery-ui/themes/flick/theme.css | 443 + .../ui-bg_diagonals-small_40_db4865_40x40.png | Bin 0 -> 390 bytes .../ui-bg_diagonals-small_50_93c3cd_40x40.png | Bin 0 -> 391 bytes .../ui-bg_diagonals-small_50_ff3853_40x40.png | Bin 0 -> 388 bytes .../ui-bg_diagonals-small_75_ccd232_40x40.png | Bin 0 -> 391 bytes .../ui-bg_dots-medium_80_ffff38_4x4.png | Bin 0 -> 283 bytes .../images/ui-bg_dots-small_35_35414f_2x2.png | Bin 0 -> 281 bytes .../ui-bg_white-lines_85_f7f7ba_40x100.png | Bin 0 -> 422 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 7090 bytes .../images/ui-icons_88a206_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_c02669_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_e1e463_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffeb33_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/hot-sneaks/jquery-ui.css | 1311 ++ .../themes/hot-sneaks/jquery-ui.min.css | 7 + .../jquery-ui/themes/hot-sneaks/theme.css | 443 + .../images/ui-bg_glass_100_f5f0e5_1x400.png | Bin 0 -> 412 bytes .../images/ui-bg_glass_25_cb842e_1x400.png | Bin 0 -> 393 bytes .../images/ui-bg_glass_70_ede4d4_1x400.png | Bin 0 -> 409 bytes .../ui-bg_highlight-hard_100_f4f0ec_1x100.png | Bin 0 -> 385 bytes .../ui-bg_highlight-hard_65_fee4bd_1x100.png | Bin 0 -> 372 bytes .../ui-bg_highlight-hard_75_f5f5b5_1x100.png | Bin 0 -> 381 bytes .../ui-bg_inset-soft_100_f4f0ec_1x100.png | Bin 0 -> 461 bytes .../images/ui-icons_c47a23_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_cb672b_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_f08000_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_f35f07_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ff7519_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/humanity/jquery-ui.css | 1311 ++ .../themes/humanity/jquery-ui.min.css | 7 + .../jquery-ui/themes/humanity/theme.css | 443 + .../ui-bg_diagonals-small_0_aaaaaa_40x40.png | Bin 0 -> 265 bytes .../ui-bg_diagonals-thick_15_444444_40x40.png | Bin 0 -> 383 bytes .../ui-bg_diagonals-thick_95_ffdc2e_40x40.png | Bin 0 -> 469 bytes .../images/ui-bg_glass_55_fbf5d0_1x400.png | Bin 0 -> 394 bytes .../ui-bg_highlight-hard_30_285c00_1x100.png | Bin 0 -> 382 bytes .../ui-bg_highlight-soft_33_3a8104_1x100.png | Bin 0 -> 403 bytes .../ui-bg_highlight-soft_50_4eb305_1x100.png | Bin 0 -> 409 bytes .../ui-bg_highlight-soft_60_4ca20b_1x100.png | Bin 0 -> 417 bytes .../ui-bg_inset-soft_10_285c00_1x100.png | Bin 0 -> 424 bytes .../images/ui-icons_4eb305_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_72b42d_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/le-frog/jquery-ui.css | 1311 ++ .../themes/le-frog/jquery-ui.min.css | 7 + .../jquery-ui/themes/le-frog/theme.css | 443 + .../images/ui-bg_glass_15_5f391b_1x400.png | Bin 0 -> 393 bytes .../ui-bg_gloss-wave_20_1c160d_500x100.png | Bin 0 -> 5851 bytes .../ui-bg_gloss-wave_25_453326_500x100.png | Bin 0 -> 5910 bytes .../ui-bg_gloss-wave_30_44372c_500x100.png | Bin 0 -> 5972 bytes .../ui-bg_highlight-soft_20_201913_1x100.png | Bin 0 -> 433 bytes .../ui-bg_highlight-soft_20_619226_1x100.png | Bin 0 -> 401 bytes .../ui-bg_inset-soft_10_201913_1x100.png | Bin 0 -> 438 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 7025 bytes .../images/ui-icons_9bcc60_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_add978_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_e3ddc9_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_f1fd86_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/mint-choc/jquery-ui.css | 1311 ++ .../themes/mint-choc/jquery-ui.min.css | 7 + .../jquery-ui/themes/mint-choc/theme.css | 443 + .../images/ui-bg_glass_100_f8f8f8_1x400.png | Bin 0 -> 324 bytes .../images/ui-bg_glass_35_dddddd_1x400.png | Bin 0 -> 323 bytes .../images/ui-bg_glass_60_eeeeee_1x400.png | Bin 0 -> 323 bytes .../ui-bg_inset-hard_75_999999_1x100.png | Bin 0 -> 310 bytes .../ui-bg_inset-soft_50_c9c9c9_1x100.png | Bin 0 -> 329 bytes .../images/ui-icons_3383bb_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 7090 bytes .../images/ui-icons_70b2e1_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_999999_256x240.png | Bin 0 -> 7111 bytes .../images/ui-icons_fbc856_256x240.png | Bin 0 -> 4676 bytes .../jquery-ui/themes/overcast/jquery-ui.css | 1311 ++ .../themes/overcast/jquery-ui.min.css | 7 + .../jquery-ui/themes/overcast/theme.css | 443 + .../ui-bg_diagonal-maze_20_6e4f1c_10x10.png | Bin 0 -> 354 bytes .../ui-bg_diagonal-maze_40_000000_10x10.png | Bin 0 -> 301 bytes .../ui-bg_fine-grain_10_eceadf_60x60.png | Bin 0 -> 10817 bytes .../ui-bg_fine-grain_10_f8f7f6_60x60.png | Bin 0 -> 9962 bytes .../ui-bg_fine-grain_15_eceadf_60x60.png | Bin 0 -> 10587 bytes .../ui-bg_fine-grain_15_f7f3de_60x60.png | Bin 0 -> 10949 bytes .../ui-bg_fine-grain_15_ffffff_60x60.png | Bin 0 -> 4262 bytes .../ui-bg_fine-grain_65_654b24_60x60.png | Bin 0 -> 14498 bytes .../ui-bg_fine-grain_68_b83400_60x60.png | Bin 0 -> 11935 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 7025 bytes .../images/ui-icons_3572ac_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_8c291d_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_b83400_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_fbdb93_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../themes/pepper-grinder/jquery-ui.css | 1311 ++ .../themes/pepper-grinder/jquery-ui.min.css | 7 + .../jquery-ui/themes/pepper-grinder/theme.css | 443 + .../images/ui-bg_glass_75_d0e5f5_1x400.png | Bin 0 -> 394 bytes .../images/ui-bg_glass_85_dfeffc_1x400.png | Bin 0 -> 399 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 390 bytes .../ui-bg_gloss-wave_55_5c9ccc_500x100.png | Bin 0 -> 5882 bytes .../ui-bg_inset-hard_100_f5f8f9_1x100.png | Bin 0 -> 391 bytes .../ui-bg_inset-hard_100_fcfdfd_1x100.png | Bin 0 -> 350 bytes .../images/ui-icons_217bc0_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_469bdd_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_6da8d5_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_d8e7f3_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_f9bd01_256x240.png | Bin 0 -> 4676 bytes .../jquery-ui/themes/redmond/jquery-ui.css | 1311 ++ .../themes/redmond/jquery-ui.min.css | 7 + .../jquery-ui/themes/redmond/theme.css | 443 + .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 393 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 265 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 323 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 324 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 390 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 325 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 7025 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 7090 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 7111 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4676 bytes .../jquery-ui/themes/smoothness/jquery-ui.css | 1311 ++ .../themes/smoothness/jquery-ui.min.css | 7 + .../jquery-ui/themes/smoothness/theme.css | 443 + .../images/ui-bg_glass_55_fcf0ba_1x400.png | Bin 0 -> 391 bytes .../ui-bg_gloss-wave_100_ece8da_500x100.png | Bin 0 -> 5817 bytes .../ui-bg_highlight-hard_100_f5f3e5_1x100.png | Bin 0 -> 394 bytes .../ui-bg_highlight-hard_100_fafaf4_1x100.png | Bin 0 -> 379 bytes .../ui-bg_highlight-hard_15_459e00_1x100.png | Bin 0 -> 380 bytes .../ui-bg_highlight-hard_95_cccccc_1x100.png | Bin 0 -> 317 bytes .../ui-bg_highlight-soft_25_67b021_1x100.png | Bin 0 -> 411 bytes .../ui-bg_highlight-soft_95_ffedad_1x100.png | Bin 0 -> 409 bytes .../ui-bg_inset-soft_15_2b2922_1x100.png | Bin 0 -> 380 bytes .../images/ui-icons_808080_256x240.png | Bin 0 -> 7117 bytes .../images/ui-icons_847e71_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_8DC262_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_eeeeee_256x240.png | Bin 0 -> 7010 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../themes/south-street/jquery-ui.css | 1311 ++ .../themes/south-street/jquery-ui.min.css | 7 + .../jquery-ui/themes/south-street/theme.css | 443 + .../images/ui-bg_glass_45_0078ae_1x400.png | Bin 0 -> 403 bytes .../images/ui-bg_glass_55_f8da4e_1x400.png | Bin 0 -> 403 bytes .../images/ui-bg_glass_75_79c9ec_1x400.png | Bin 0 -> 406 bytes .../ui-bg_gloss-wave_45_e14f1c_500x100.png | Bin 0 -> 5922 bytes .../ui-bg_gloss-wave_50_6eac2c_500x100.png | Bin 0 -> 5964 bytes .../ui-bg_gloss-wave_75_2191c0_500x100.png | Bin 0 -> 6035 bytes .../ui-bg_inset-hard_100_fcfdfd_1x100.png | Bin 0 -> 350 bytes .../start/images/ui-icons_0078ae_256x240.png | Bin 0 -> 4676 bytes .../start/images/ui-icons_056b93_256x240.png | Bin 0 -> 4676 bytes .../start/images/ui-icons_d8e7f3_256x240.png | Bin 0 -> 4676 bytes .../start/images/ui-icons_e0fdff_256x240.png | Bin 0 -> 4676 bytes .../start/images/ui-icons_f5e175_256x240.png | Bin 0 -> 4676 bytes .../start/images/ui-icons_f7a50d_256x240.png | Bin 0 -> 4676 bytes .../start/images/ui-icons_fcd113_256x240.png | Bin 0 -> 4676 bytes .../jquery-ui/themes/start/jquery-ui.css | 1311 ++ .../jquery-ui/themes/start/jquery-ui.min.css | 7 + third_party/jquery-ui/themes/start/theme.css | 443 + ...ui-bg_diagonals-medium_20_d34d17_40x40.png | Bin 0 -> 440 bytes .../ui-bg_gloss-wave_45_817865_500x100.png | Bin 0 -> 5939 bytes .../ui-bg_gloss-wave_60_fece2f_500x100.png | Bin 0 -> 5908 bytes .../ui-bg_gloss-wave_70_ffdd57_500x100.png | Bin 0 -> 5601 bytes .../ui-bg_gloss-wave_90_fff9e5_500x100.png | Bin 0 -> 5447 bytes .../ui-bg_highlight-soft_100_feeebd_1x100.png | Bin 0 -> 401 bytes .../ui-bg_inset-soft_30_ffffff_1x100.png | Bin 0 -> 261 bytes .../sunny/images/ui-icons_3d3d3d_256x240.png | Bin 0 -> 7074 bytes .../sunny/images/ui-icons_bd7b00_256x240.png | Bin 0 -> 4676 bytes .../sunny/images/ui-icons_d19405_256x240.png | Bin 0 -> 4676 bytes .../sunny/images/ui-icons_eb990f_256x240.png | Bin 0 -> 4676 bytes .../sunny/images/ui-icons_ed9f26_256x240.png | Bin 0 -> 4676 bytes .../sunny/images/ui-icons_fadc7a_256x240.png | Bin 0 -> 4676 bytes .../sunny/images/ui-icons_ffe180_256x240.png | Bin 0 -> 4676 bytes .../jquery-ui/themes/sunny/jquery-ui.css | 1311 ++ .../jquery-ui/themes/sunny/jquery-ui.min.css | 7 + third_party/jquery-ui/themes/sunny/theme.css | 443 + .../images/ui-bg_diamond_10_4f4221_10x8.png | Bin 0 -> 365 bytes .../images/ui-bg_diamond_20_372806_10x8.png | Bin 0 -> 368 bytes .../images/ui-bg_diamond_25_675423_10x8.png | Bin 0 -> 370 bytes .../images/ui-bg_diamond_25_d5ac5d_10x8.png | Bin 0 -> 371 bytes .../images/ui-bg_diamond_8_261803_10x8.png | Bin 0 -> 368 bytes .../images/ui-bg_diamond_8_443113_10x8.png | Bin 0 -> 368 bytes .../ui-bg_highlight-hard_65_fee4bd_1x100.png | Bin 0 -> 372 bytes .../images/ui-icons_070603_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_e8e2b5_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_e9cd86_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_efec9f_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_f2ec64_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_f9f2bd_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ff7519_256x240.png | Bin 0 -> 4676 bytes .../themes/swanky-purse/jquery-ui.css | 1311 ++ .../themes/swanky-purse/jquery-ui.min.css | 7 + .../jquery-ui/themes/swanky-purse/theme.css | 443 + .../ui-bg_diagonals-small_50_262626_40x40.png | Bin 0 -> 321 bytes .../images/ui-bg_glass_40_0a0a0a_1x400.png | Bin 0 -> 322 bytes .../images/ui-bg_glass_55_f1fbe5_1x400.png | Bin 0 -> 406 bytes .../images/ui-bg_glass_60_000000_1x400.png | Bin 0 -> 323 bytes .../ui-bg_gloss-wave_55_000000_500x100.png | Bin 0 -> 4360 bytes .../ui-bg_gloss-wave_85_9fda58_500x100.png | Bin 0 -> 5998 bytes .../ui-bg_gloss-wave_95_f6ecd5_500x100.png | Bin 0 -> 5856 bytes .../images/ui-icons_000000_256x240.png | Bin 0 -> 5582 bytes .../images/ui-icons_1f1f1f_256x240.png | Bin 0 -> 7025 bytes .../images/ui-icons_9fda58_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_b8ec79_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../jquery-ui/themes/trontastic/jquery-ui.css | 1311 ++ .../themes/trontastic/jquery-ui.min.css | 7 + .../jquery-ui/themes/trontastic/theme.css | 443 + .../images/ui-bg_glass_20_555555_1x400.png | Bin 0 -> 318 bytes .../images/ui-bg_glass_40_0078a3_1x400.png | Bin 0 -> 400 bytes .../images/ui-bg_glass_40_ffc73d_1x400.png | Bin 0 -> 374 bytes .../ui-bg_gloss-wave_25_333333_500x100.png | Bin 0 -> 3976 bytes .../ui-bg_highlight-soft_80_eeeeee_1x100.png | Bin 0 -> 335 bytes .../ui-bg_inset-soft_25_000000_1x100.png | Bin 0 -> 312 bytes .../ui-bg_inset-soft_30_f58400_1x100.png | Bin 0 -> 398 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 7025 bytes .../images/ui-icons_4b8e0b_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_a83300_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_cccccc_256x240.png | Bin 0 -> 7034 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../themes/ui-darkness/jquery-ui.css | 1311 ++ .../themes/ui-darkness/jquery-ui.min.css | 7 + .../jquery-ui/themes/ui-darkness/theme.css | 443 + .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 0 -> 476 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 0 -> 384 bytes .../images/ui-bg_glass_100_f6f6f6_1x400.png | Bin 0 -> 324 bytes .../images/ui-bg_glass_100_fdf5ce_1x400.png | Bin 0 -> 406 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 265 bytes .../ui-bg_gloss-wave_35_f6a828_500x100.png | Bin 0 -> 5873 bytes .../ui-bg_highlight-soft_100_eeeeee_1x100.png | Bin 0 -> 342 bytes .../ui-bg_highlight-soft_75_ffe45c_1x100.png | Bin 0 -> 386 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 7025 bytes .../images/ui-icons_228ef1_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ef8c08_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffd27a_256x240.png | Bin 0 -> 4676 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6487 bytes .../themes/ui-lightness/jquery-ui.css | 1311 ++ .../themes/ui-lightness/jquery-ui.min.css | 7 + .../jquery-ui/themes/ui-lightness/theme.css | 443 + .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 390 bytes .../ui-bg_gloss-wave_16_121212_500x100.png | Bin 0 -> 4031 bytes .../ui-bg_highlight-hard_15_888888_1x100.png | Bin 0 -> 311 bytes .../ui-bg_highlight-hard_55_555555_1x100.png | Bin 0 -> 311 bytes .../ui-bg_highlight-soft_35_adadad_1x100.png | Bin 0 -> 326 bytes .../ui-bg_highlight-soft_60_dddddd_1x100.png | Bin 0 -> 342 bytes .../ui-bg_inset-soft_15_121212_1x100.png | Bin 0 -> 322 bytes .../vader/images/ui-icons_666666_256x240.png | Bin 0 -> 7111 bytes .../vader/images/ui-icons_aaaaaa_256x240.png | Bin 0 -> 7075 bytes .../vader/images/ui-icons_bbbbbb_256x240.png | Bin 0 -> 7092 bytes .../vader/images/ui-icons_c98000_256x240.png | Bin 0 -> 4676 bytes .../vader/images/ui-icons_cccccc_256x240.png | Bin 0 -> 7034 bytes .../vader/images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4676 bytes .../vader/images/ui-icons_f29a00_256x240.png | Bin 0 -> 4676 bytes .../jquery-ui/themes/vader/jquery-ui.css | 1311 ++ .../jquery-ui/themes/vader/jquery-ui.min.css | 7 + third_party/jquery-ui/themes/vader/theme.css | 443 + third_party/jquery-ui/ui/.jshintrc | 24 + third_party/jquery-ui/ui/core.js | 21 + third_party/jquery-ui/ui/data.js | 39 + third_party/jquery-ui/ui/disable-selection.js | 46 + third_party/jquery-ui/ui/effect.js | 1635 ++ .../jquery-ui/ui/effects/effect-blind.js | 70 + .../jquery-ui/ui/effects/effect-bounce.js | 110 + .../jquery-ui/ui/effects/effect-clip.js | 65 + .../jquery-ui/ui/effects/effect-drop.js | 69 + .../jquery-ui/ui/effects/effect-explode.js | 111 + .../jquery-ui/ui/effects/effect-fade.js | 47 + .../jquery-ui/ui/effects/effect-fold.js | 89 + .../jquery-ui/ui/effects/effect-highlight.js | 57 + .../jquery-ui/ui/effects/effect-puff.js | 42 + .../jquery-ui/ui/effects/effect-pulsate.js | 64 + .../jquery-ui/ui/effects/effect-scale.js | 56 + .../jquery-ui/ui/effects/effect-shake.js | 74 + .../jquery-ui/ui/effects/effect-size.js | 191 + .../jquery-ui/ui/effects/effect-slide.js | 76 + .../jquery-ui/ui/effects/effect-transfer.js | 40 + third_party/jquery-ui/ui/escape-selector.js | 21 + third_party/jquery-ui/ui/focusable.js | 84 + third_party/jquery-ui/ui/form-reset-mixin.js | 77 + third_party/jquery-ui/ui/form.js | 20 + .../jquery-ui/ui/i18n/datepicker-af.js | 37 + .../jquery-ui/ui/i18n/datepicker-ar-DZ.js | 39 + .../jquery-ui/ui/i18n/datepicker-ar.js | 39 + .../jquery-ui/ui/i18n/datepicker-az.js | 37 + .../jquery-ui/ui/i18n/datepicker-be.js | 37 + .../jquery-ui/ui/i18n/datepicker-bg.js | 38 + .../jquery-ui/ui/i18n/datepicker-bs.js | 37 + .../jquery-ui/ui/i18n/datepicker-ca.js | 37 + .../jquery-ui/ui/i18n/datepicker-cs.js | 37 + .../jquery-ui/ui/i18n/datepicker-cy-GB.js | 45 + .../jquery-ui/ui/i18n/datepicker-da.js | 37 + .../jquery-ui/ui/i18n/datepicker-de.js | 37 + .../jquery-ui/ui/i18n/datepicker-el.js | 37 + .../jquery-ui/ui/i18n/datepicker-en-AU.js | 37 + .../jquery-ui/ui/i18n/datepicker-en-GB.js | 37 + .../jquery-ui/ui/i18n/datepicker-en-NZ.js | 37 + .../jquery-ui/ui/i18n/datepicker-eo.js | 37 + .../jquery-ui/ui/i18n/datepicker-es.js | 37 + .../jquery-ui/ui/i18n/datepicker-et.js | 45 + .../jquery-ui/ui/i18n/datepicker-eu.js | 36 + .../jquery-ui/ui/i18n/datepicker-fa.js | 73 + .../jquery-ui/ui/i18n/datepicker-fi.js | 37 + .../jquery-ui/ui/i18n/datepicker-fo.js | 45 + .../jquery-ui/ui/i18n/datepicker-fr-CA.js | 37 + .../jquery-ui/ui/i18n/datepicker-fr-CH.js | 37 + .../jquery-ui/ui/i18n/datepicker-fr.js | 39 + .../jquery-ui/ui/i18n/datepicker-gl.js | 37 + .../jquery-ui/ui/i18n/datepicker-he.js | 37 + .../jquery-ui/ui/i18n/datepicker-hi.js | 37 + .../jquery-ui/ui/i18n/datepicker-hr.js | 37 + .../jquery-ui/ui/i18n/datepicker-hu.js | 36 + .../jquery-ui/ui/i18n/datepicker-hy.js | 37 + .../jquery-ui/ui/i18n/datepicker-id.js | 37 + .../jquery-ui/ui/i18n/datepicker-is.js | 45 + .../jquery-ui/ui/i18n/datepicker-it-CH.js | 37 + .../jquery-ui/ui/i18n/datepicker-it.js | 37 + .../jquery-ui/ui/i18n/datepicker-ja.js | 37 + .../jquery-ui/ui/i18n/datepicker-ka.js | 48 + .../jquery-ui/ui/i18n/datepicker-kk.js | 37 + .../jquery-ui/ui/i18n/datepicker-km.js | 37 + .../jquery-ui/ui/i18n/datepicker-ko.js | 37 + .../jquery-ui/ui/i18n/datepicker-ky.js | 38 + .../jquery-ui/ui/i18n/datepicker-lb.js | 45 + .../jquery-ui/ui/i18n/datepicker-lt.js | 45 + .../jquery-ui/ui/i18n/datepicker-lv.js | 45 + .../jquery-ui/ui/i18n/datepicker-mk.js | 37 + .../jquery-ui/ui/i18n/datepicker-ml.js | 37 + .../jquery-ui/ui/i18n/datepicker-ms.js | 37 + .../jquery-ui/ui/i18n/datepicker-nb.js | 49 + .../jquery-ui/ui/i18n/datepicker-nl-BE.js | 37 + .../jquery-ui/ui/i18n/datepicker-nl.js | 37 + .../jquery-ui/ui/i18n/datepicker-nn.js | 49 + .../jquery-ui/ui/i18n/datepicker-no.js | 50 + .../jquery-ui/ui/i18n/datepicker-pl.js | 37 + .../jquery-ui/ui/i18n/datepicker-pt-BR.js | 45 + .../jquery-ui/ui/i18n/datepicker-pt.js | 44 + .../jquery-ui/ui/i18n/datepicker-rm.js | 61 + .../jquery-ui/ui/i18n/datepicker-ro.js | 40 + .../jquery-ui/ui/i18n/datepicker-ru.js | 37 + .../jquery-ui/ui/i18n/datepicker-sk.js | 37 + .../jquery-ui/ui/i18n/datepicker-sl.js | 38 + .../jquery-ui/ui/i18n/datepicker-sq.js | 37 + .../jquery-ui/ui/i18n/datepicker-sr-SR.js | 37 + .../jquery-ui/ui/i18n/datepicker-sr.js | 37 + .../jquery-ui/ui/i18n/datepicker-sv.js | 37 + .../jquery-ui/ui/i18n/datepicker-ta.js | 53 + .../jquery-ui/ui/i18n/datepicker-th.js | 37 + .../jquery-ui/ui/i18n/datepicker-tj.js | 37 + .../jquery-ui/ui/i18n/datepicker-tr.js | 37 + .../jquery-ui/ui/i18n/datepicker-uk.js | 38 + .../jquery-ui/ui/i18n/datepicker-vi.js | 37 + .../jquery-ui/ui/i18n/datepicker-zh-CN.js | 37 + .../jquery-ui/ui/i18n/datepicker-zh-HK.js | 37 + .../jquery-ui/ui/i18n/datepicker-zh-TW.js | 37 + third_party/jquery-ui/ui/ie.js | 15 + third_party/jquery-ui/ui/jquery-1-7.js | 89 + third_party/jquery-ui/ui/keycode.js | 45 + third_party/jquery-ui/ui/labels.js | 62 + third_party/jquery-ui/ui/minified/core.js | 4 + third_party/jquery-ui/ui/minified/data.js | 4 + .../ui/minified/disable-selection.js | 4 + third_party/jquery-ui/ui/minified/effect.js | 4 + .../jquery-ui/ui/minified/escape-selector.js | 4 + .../jquery-ui/ui/minified/focusable.js | 4 + .../jquery-ui/ui/minified/form-reset-mixin.js | 4 + third_party/jquery-ui/ui/minified/form.js | 4 + .../ui/minified/i18n/datepicker-af.js | 4 + .../ui/minified/i18n/datepicker-ar-DZ.js | 4 + .../ui/minified/i18n/datepicker-ar.js | 4 + .../ui/minified/i18n/datepicker-az.js | 4 + .../ui/minified/i18n/datepicker-be.js | 4 + .../ui/minified/i18n/datepicker-bg.js | 4 + .../ui/minified/i18n/datepicker-bs.js | 4 + .../ui/minified/i18n/datepicker-ca.js | 4 + .../ui/minified/i18n/datepicker-cs.js | 4 + .../ui/minified/i18n/datepicker-cy-GB.js | 4 + .../ui/minified/i18n/datepicker-da.js | 4 + .../ui/minified/i18n/datepicker-de.js | 4 + .../ui/minified/i18n/datepicker-el.js | 4 + .../ui/minified/i18n/datepicker-en-AU.js | 4 + .../ui/minified/i18n/datepicker-en-GB.js | 4 + .../ui/minified/i18n/datepicker-en-NZ.js | 4 + .../ui/minified/i18n/datepicker-eo.js | 4 + .../ui/minified/i18n/datepicker-es.js | 4 + .../ui/minified/i18n/datepicker-et.js | 4 + .../ui/minified/i18n/datepicker-eu.js | 4 + .../ui/minified/i18n/datepicker-fa.js | 4 + .../ui/minified/i18n/datepicker-fi.js | 4 + .../ui/minified/i18n/datepicker-fo.js | 4 + .../ui/minified/i18n/datepicker-fr-CA.js | 4 + .../ui/minified/i18n/datepicker-fr-CH.js | 4 + .../ui/minified/i18n/datepicker-fr.js | 4 + .../ui/minified/i18n/datepicker-gl.js | 4 + .../ui/minified/i18n/datepicker-he.js | 4 + .../ui/minified/i18n/datepicker-hi.js | 4 + .../ui/minified/i18n/datepicker-hr.js | 4 + .../ui/minified/i18n/datepicker-hu.js | 4 + .../ui/minified/i18n/datepicker-hy.js | 4 + .../ui/minified/i18n/datepicker-id.js | 4 + .../ui/minified/i18n/datepicker-is.js | 4 + .../ui/minified/i18n/datepicker-it-CH.js | 4 + .../ui/minified/i18n/datepicker-it.js | 4 + .../ui/minified/i18n/datepicker-ja.js | 4 + .../ui/minified/i18n/datepicker-ka.js | 4 + .../ui/minified/i18n/datepicker-kk.js | 4 + .../ui/minified/i18n/datepicker-km.js | 4 + .../ui/minified/i18n/datepicker-ko.js | 4 + .../ui/minified/i18n/datepicker-ky.js | 4 + .../ui/minified/i18n/datepicker-lb.js | 4 + .../ui/minified/i18n/datepicker-lt.js | 4 + .../ui/minified/i18n/datepicker-lv.js | 4 + .../ui/minified/i18n/datepicker-mk.js | 4 + .../ui/minified/i18n/datepicker-ml.js | 4 + .../ui/minified/i18n/datepicker-ms.js | 4 + .../ui/minified/i18n/datepicker-nb.js | 4 + .../ui/minified/i18n/datepicker-nl-BE.js | 4 + .../ui/minified/i18n/datepicker-nl.js | 4 + .../ui/minified/i18n/datepicker-nn.js | 4 + .../ui/minified/i18n/datepicker-no.js | 4 + .../ui/minified/i18n/datepicker-pl.js | 4 + .../ui/minified/i18n/datepicker-pt-BR.js | 4 + .../ui/minified/i18n/datepicker-pt.js | 4 + .../ui/minified/i18n/datepicker-rm.js | 4 + .../ui/minified/i18n/datepicker-ro.js | 4 + .../ui/minified/i18n/datepicker-ru.js | 4 + .../ui/minified/i18n/datepicker-sk.js | 4 + .../ui/minified/i18n/datepicker-sl.js | 4 + .../ui/minified/i18n/datepicker-sq.js | 4 + .../ui/minified/i18n/datepicker-sr-SR.js | 4 + .../ui/minified/i18n/datepicker-sr.js | 4 + .../ui/minified/i18n/datepicker-sv.js | 4 + .../ui/minified/i18n/datepicker-ta.js | 4 + .../ui/minified/i18n/datepicker-th.js | 4 + .../ui/minified/i18n/datepicker-tj.js | 4 + .../ui/minified/i18n/datepicker-tr.js | 4 + .../ui/minified/i18n/datepicker-uk.js | 4 + .../ui/minified/i18n/datepicker-vi.js | 4 + .../ui/minified/i18n/datepicker-zh-CN.js | 4 + .../ui/minified/i18n/datepicker-zh-HK.js | 4 + .../ui/minified/i18n/datepicker-zh-TW.js | 4 + third_party/jquery-ui/ui/minified/ie.js | 4 + .../jquery-ui/ui/minified/jquery-1-7.js | 4 + third_party/jquery-ui/ui/minified/keycode.js | 4 + third_party/jquery-ui/ui/minified/labels.js | 4 + third_party/jquery-ui/ui/minified/plugin.js | 4 + third_party/jquery-ui/ui/minified/position.js | 4 + .../ui/minified/safe-active-element.js | 4 + .../jquery-ui/ui/minified/safe-blur.js | 4 + .../jquery-ui/ui/minified/scroll-parent.js | 4 + third_party/jquery-ui/ui/minified/tabbable.js | 4 + .../jquery-ui/ui/minified/unique-id.js | 4 + third_party/jquery-ui/ui/minified/version.js | 4 + third_party/jquery-ui/ui/minified/widget.js | 4 + third_party/jquery-ui/ui/plugin.js | 44 + third_party/jquery-ui/ui/position.js | 498 + .../jquery-ui/ui/safe-active-element.js | 40 + third_party/jquery-ui/ui/safe-blur.js | 21 + third_party/jquery-ui/ui/scroll-parent.js | 45 + third_party/jquery-ui/ui/tabbable.js | 35 + third_party/jquery-ui/ui/unique-id.js | 49 + third_party/jquery-ui/ui/version.js | 17 + third_party/jquery-ui/ui/widget.js | 733 + third_party/jquery-ui/ui/widgets/accordion.js | 613 + .../jquery-ui/ui/widgets/autocomplete.js | 682 + third_party/jquery-ui/ui/widgets/button.js | 386 + .../jquery-ui/ui/widgets/checkboxradio.js | 286 + .../jquery-ui/ui/widgets/controlgroup.js | 298 + .../jquery-ui/ui/widgets/datepicker.js | 2120 ++ third_party/jquery-ui/ui/widgets/dialog.js | 940 + third_party/jquery-ui/ui/widgets/draggable.js | 1250 ++ third_party/jquery-ui/ui/widgets/droppable.js | 497 + third_party/jquery-ui/ui/widgets/menu.js | 673 + third_party/jquery-ui/ui/widgets/mouse.js | 226 + .../jquery-ui/ui/widgets/progressbar.js | 178 + third_party/jquery-ui/ui/widgets/resizable.js | 1201 + .../jquery-ui/ui/widgets/selectable.js | 310 + .../jquery-ui/ui/widgets/selectmenu.js | 687 + third_party/jquery-ui/ui/widgets/slider.js | 752 + third_party/jquery-ui/ui/widgets/sortable.js | 1554 ++ third_party/jquery-ui/ui/widgets/spinner.js | 575 + third_party/jquery-ui/ui/widgets/tabs.js | 924 + third_party/jquery-ui/ui/widgets/tooltip.js | 520 + tsconfig.json | 7 +- 648 files changed, 87538 insertions(+), 100 deletions(-) delete mode 100644 .bowerrc create mode 100644 third_party/angular-ui-sortable/.bower.json create mode 100644 third_party/angular-ui-sortable/.travis.yml create mode 100644 third_party/angular-ui-sortable/bower.json create mode 100644 third_party/angular-ui-sortable/sortable.js create mode 100644 third_party/angular-ui-sortable/sortable.min.js create mode 100644 third_party/jquery-ui/.bower.json create mode 100644 third_party/jquery-ui/.gitignore create mode 100644 third_party/jquery-ui/README.md create mode 100644 third_party/jquery-ui/bower.json create mode 100644 third_party/jquery-ui/component.json create mode 100644 third_party/jquery-ui/composer.json create mode 100644 third_party/jquery-ui/jquery-ui.js create mode 100644 third_party/jquery-ui/jquery-ui.min.js create mode 100644 third_party/jquery-ui/package.json create mode 100644 third_party/jquery-ui/themes/base/accordion.css create mode 100644 third_party/jquery-ui/themes/base/all.css create mode 100644 third_party/jquery-ui/themes/base/autocomplete.css create mode 100644 third_party/jquery-ui/themes/base/base.css create mode 100644 third_party/jquery-ui/themes/base/button.css create mode 100644 third_party/jquery-ui/themes/base/checkboxradio.css create mode 100644 third_party/jquery-ui/themes/base/controlgroup.css create mode 100644 third_party/jquery-ui/themes/base/core.css create mode 100644 third_party/jquery-ui/themes/base/datepicker.css create mode 100644 third_party/jquery-ui/themes/base/dialog.css create mode 100644 third_party/jquery-ui/themes/base/draggable.css create mode 100644 third_party/jquery-ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 third_party/jquery-ui/themes/base/images/ui-icons_444444_256x240.png create mode 100644 third_party/jquery-ui/themes/base/images/ui-icons_555555_256x240.png create mode 100644 third_party/jquery-ui/themes/base/images/ui-icons_777620_256x240.png create mode 100644 third_party/jquery-ui/themes/base/images/ui-icons_777777_256x240.png create mode 100644 third_party/jquery-ui/themes/base/images/ui-icons_cc0000_256x240.png create mode 100644 third_party/jquery-ui/themes/base/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/base/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/base/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/base/menu.css create mode 100644 third_party/jquery-ui/themes/base/progressbar.css create mode 100644 third_party/jquery-ui/themes/base/resizable.css create mode 100644 third_party/jquery-ui/themes/base/selectable.css create mode 100644 third_party/jquery-ui/themes/base/selectmenu.css create mode 100644 third_party/jquery-ui/themes/base/slider.css create mode 100644 third_party/jquery-ui/themes/base/sortable.css create mode 100644 third_party/jquery-ui/themes/base/spinner.css create mode 100644 third_party/jquery-ui/themes/base/tabs.css create mode 100644 third_party/jquery-ui/themes/base/theme.css create mode 100644 third_party/jquery-ui/themes/base/tooltip.css create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-bg_diagonals-thick_8_333333_40x40.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-bg_glass_40_111111_1x400.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-bg_glass_55_1c1c1c_1x400.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-bg_highlight-hard_100_f9f9f9_1x100.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-bg_highlight-hard_40_aaaaaa_1x100.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-bg_highlight-soft_50_aaaaaa_1x100.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-bg_inset-hard_45_cd0a0a_1x100.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-bg_inset-hard_55_ffeb80_1x100.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-icons_222222_256x240.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-icons_4ca300_256x240.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-icons_bbbbbb_256x240.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-icons_ededed_256x240.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-icons_ffcf29_256x240.png create mode 100644 third_party/jquery-ui/themes/black-tie/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/black-tie/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/black-tie/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/black-tie/theme.css create mode 100644 third_party/jquery-ui/themes/blitzer/images/ui-bg_diagonals-thick_75_f3d8d8_40x40.png create mode 100644 third_party/jquery-ui/themes/blitzer/images/ui-bg_dots-small_65_a6a6a6_2x2.png create mode 100644 third_party/jquery-ui/themes/blitzer/images/ui-bg_glass_55_fbf8ee_1x400.png create mode 100644 third_party/jquery-ui/themes/blitzer/images/ui-bg_highlight-hard_100_eeeeee_1x100.png create mode 100644 third_party/jquery-ui/themes/blitzer/images/ui-bg_highlight-hard_100_f6f6f6_1x100.png create mode 100644 third_party/jquery-ui/themes/blitzer/images/ui-bg_highlight-soft_15_cc0000_1x100.png create mode 100644 third_party/jquery-ui/themes/blitzer/images/ui-icons_004276_256x240.png create mode 100644 third_party/jquery-ui/themes/blitzer/images/ui-icons_cc0000_256x240.png create mode 100644 third_party/jquery-ui/themes/blitzer/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/blitzer/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/blitzer/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/blitzer/theme.css create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-bg_diagonals-thick_90_eeeeee_40x40.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-bg_glass_100_e4f1fb_1x400.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-bg_glass_50_3baae3_1x400.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-bg_glass_80_d7ebf9_1x400.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-bg_highlight-hard_70_000000_1x100.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-bg_highlight-soft_100_deedf7_1x100.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-bg_highlight-soft_25_ffef8f_1x100.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-icons_2694e8_256x240.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-icons_2e83ff_256x240.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-icons_3d80b3_256x240.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-icons_72a7cf_256x240.png create mode 100644 third_party/jquery-ui/themes/cupertino/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/cupertino/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/cupertino/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/cupertino/theme.css create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-bg_glass_40_ffc73d_1x400.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-bg_highlight-hard_20_0972a5_1x100.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-bg_highlight-soft_33_003147_1x100.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-bg_highlight-soft_35_222222_1x100.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-bg_highlight-soft_44_444444_1x100.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-bg_highlight-soft_80_eeeeee_1x100.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-bg_loop_25_000000_21x21.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-icons_222222_256x240.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-icons_4b8e0b_256x240.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-icons_a83300_256x240.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-icons_cccccc_256x240.png create mode 100644 third_party/jquery-ui/themes/dark-hive/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/dark-hive/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/dark-hive/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/dark-hive/theme.css create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-bg_dots-medium_30_0b58a2_4x4.png create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-bg_dots-small_20_333333_2x2.png create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-bg_dots-small_30_a32d00_2x2.png create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-bg_dots-small_40_00498f_2x2.png create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-bg_gloss-wave_20_111111_500x100.png create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-icons_00498f_256x240.png create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-icons_98d2fb_256x240.png create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-icons_9ccdfc_256x240.png create mode 100644 third_party/jquery-ui/themes/dot-luv/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/dot-luv/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/dot-luv/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/dot-luv/theme.css create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-bg_gloss-wave_30_3d3644_500x100.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-bg_highlight-soft_100_dcd9de_1x100.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-bg_highlight-soft_100_eae6ea_1x100.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-bg_highlight-soft_25_30273a_1x100.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-bg_highlight-soft_45_5f5964_1x100.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-icons_454545_256x240.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-icons_734d99_256x240.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-icons_8d78a5_256x240.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-icons_a8a3ae_256x240.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-icons_ebccce_256x240.png create mode 100644 third_party/jquery-ui/themes/eggplant/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/eggplant/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/eggplant/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/eggplant/theme.css create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-bg_diagonals-small_25_c5ddfc_40x40.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-bg_diagonals-thick_20_e69700_40x40.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-bg_diagonals-thick_22_1484e6_40x40.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-bg_diagonals-thick_26_2293f7_40x40.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-bg_highlight-soft_100_f9f9f9_1x100.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-bg_inset-hard_100_eeeeee_1x100.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-icons_0a82eb_256x240.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-icons_0b54d5_256x240.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-icons_5fa5e3_256x240.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-icons_fcdd4a_256x240.png create mode 100644 third_party/jquery-ui/themes/excite-bike/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/excite-bike/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/excite-bike/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/excite-bike/theme.css create mode 100644 third_party/jquery-ui/themes/flick/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 third_party/jquery-ui/themes/flick/images/ui-bg_highlight-soft_100_f6f6f6_1x100.png create mode 100644 third_party/jquery-ui/themes/flick/images/ui-bg_highlight-soft_25_0073ea_1x100.png create mode 100644 third_party/jquery-ui/themes/flick/images/ui-bg_highlight-soft_50_dddddd_1x100.png create mode 100644 third_party/jquery-ui/themes/flick/images/ui-icons_0073ea_256x240.png create mode 100644 third_party/jquery-ui/themes/flick/images/ui-icons_454545_256x240.png create mode 100644 third_party/jquery-ui/themes/flick/images/ui-icons_666666_256x240.png create mode 100644 third_party/jquery-ui/themes/flick/images/ui-icons_ff0084_256x240.png create mode 100644 third_party/jquery-ui/themes/flick/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/flick/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/flick/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/flick/theme.css create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-bg_diagonals-small_40_db4865_40x40.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-bg_diagonals-small_50_93c3cd_40x40.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-bg_diagonals-small_50_ff3853_40x40.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-bg_diagonals-small_75_ccd232_40x40.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-bg_dots-medium_80_ffff38_4x4.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-bg_dots-small_35_35414f_2x2.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-bg_white-lines_85_f7f7ba_40x100.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-icons_454545_256x240.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-icons_88a206_256x240.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-icons_c02669_256x240.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-icons_e1e463_256x240.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-icons_ffeb33_256x240.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/hot-sneaks/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/hot-sneaks/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/hot-sneaks/theme.css create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-bg_glass_100_f5f0e5_1x400.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-bg_glass_25_cb842e_1x400.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-bg_glass_70_ede4d4_1x400.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-bg_highlight-hard_100_f4f0ec_1x100.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-bg_highlight-hard_65_fee4bd_1x100.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-bg_highlight-hard_75_f5f5b5_1x100.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-bg_inset-soft_100_f4f0ec_1x100.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-icons_c47a23_256x240.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-icons_cb672b_256x240.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-icons_f08000_256x240.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-icons_f35f07_256x240.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-icons_ff7519_256x240.png create mode 100644 third_party/jquery-ui/themes/humanity/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/humanity/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/humanity/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/humanity/theme.css create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-bg_diagonals-small_0_aaaaaa_40x40.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-bg_diagonals-thick_15_444444_40x40.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-bg_diagonals-thick_95_ffdc2e_40x40.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-bg_glass_55_fbf5d0_1x400.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-bg_highlight-hard_30_285c00_1x100.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-bg_highlight-soft_33_3a8104_1x100.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-bg_highlight-soft_50_4eb305_1x100.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-bg_highlight-soft_60_4ca20b_1x100.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-bg_inset-soft_10_285c00_1x100.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-icons_4eb305_256x240.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-icons_72b42d_256x240.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-icons_cd0a0a_256x240.png create mode 100644 third_party/jquery-ui/themes/le-frog/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/le-frog/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/le-frog/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/le-frog/theme.css create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-bg_glass_15_5f391b_1x400.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-bg_gloss-wave_20_1c160d_500x100.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-bg_gloss-wave_25_453326_500x100.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-bg_gloss-wave_30_44372c_500x100.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-bg_highlight-soft_20_201913_1x100.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-bg_highlight-soft_20_619226_1x100.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-bg_inset-soft_10_201913_1x100.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-icons_222222_256x240.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-icons_9bcc60_256x240.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-icons_add978_256x240.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-icons_e3ddc9_256x240.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-icons_f1fd86_256x240.png create mode 100644 third_party/jquery-ui/themes/mint-choc/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/mint-choc/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/mint-choc/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/mint-choc/theme.css create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-bg_glass_100_f8f8f8_1x400.png create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-bg_glass_35_dddddd_1x400.png create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-bg_glass_60_eeeeee_1x400.png create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-bg_inset-hard_75_999999_1x100.png create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-bg_inset-soft_50_c9c9c9_1x100.png create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-icons_3383bb_256x240.png create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-icons_454545_256x240.png create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-icons_70b2e1_256x240.png create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-icons_999999_256x240.png create mode 100644 third_party/jquery-ui/themes/overcast/images/ui-icons_fbc856_256x240.png create mode 100644 third_party/jquery-ui/themes/overcast/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/overcast/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/overcast/theme.css create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-bg_diagonal-maze_20_6e4f1c_10x10.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-bg_diagonal-maze_40_000000_10x10.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-bg_fine-grain_10_eceadf_60x60.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-bg_fine-grain_10_f8f7f6_60x60.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-bg_fine-grain_15_eceadf_60x60.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-bg_fine-grain_15_f7f3de_60x60.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-bg_fine-grain_15_ffffff_60x60.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-bg_fine-grain_65_654b24_60x60.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-bg_fine-grain_68_b83400_60x60.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-icons_222222_256x240.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-icons_3572ac_256x240.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-icons_8c291d_256x240.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-icons_b83400_256x240.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-icons_fbdb93_256x240.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/pepper-grinder/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/pepper-grinder/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/pepper-grinder/theme.css create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-bg_glass_85_dfeffc_1x400.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-icons_217bc0_256x240.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-icons_2e83ff_256x240.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-icons_469bdd_256x240.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-icons_6da8d5_256x240.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-icons_cd0a0a_256x240.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-icons_d8e7f3_256x240.png create mode 100644 third_party/jquery-ui/themes/redmond/images/ui-icons_f9bd01_256x240.png create mode 100644 third_party/jquery-ui/themes/redmond/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/redmond/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/redmond/theme.css create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-icons_222222_256x240.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-icons_454545_256x240.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-icons_888888_256x240.png create mode 100644 third_party/jquery-ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png create mode 100644 third_party/jquery-ui/themes/smoothness/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/smoothness/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/smoothness/theme.css create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-bg_glass_55_fcf0ba_1x400.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-bg_gloss-wave_100_ece8da_500x100.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-bg_highlight-hard_100_f5f3e5_1x100.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-bg_highlight-hard_100_fafaf4_1x100.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-bg_highlight-hard_15_459e00_1x100.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-bg_highlight-hard_95_cccccc_1x100.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-bg_highlight-soft_25_67b021_1x100.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-bg_highlight-soft_95_ffedad_1x100.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-bg_inset-soft_15_2b2922_1x100.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-icons_808080_256x240.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-icons_847e71_256x240.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-icons_8DC262_256x240.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-icons_cd0a0a_256x240.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-icons_eeeeee_256x240.png create mode 100644 third_party/jquery-ui/themes/south-street/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/south-street/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/south-street/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/south-street/theme.css create mode 100644 third_party/jquery-ui/themes/start/images/ui-bg_glass_45_0078ae_1x400.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-bg_glass_55_f8da4e_1x400.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-bg_glass_75_79c9ec_1x400.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-bg_gloss-wave_75_2191c0_500x100.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-icons_0078ae_256x240.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-icons_056b93_256x240.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-icons_d8e7f3_256x240.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-icons_e0fdff_256x240.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-icons_f5e175_256x240.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-icons_f7a50d_256x240.png create mode 100644 third_party/jquery-ui/themes/start/images/ui-icons_fcd113_256x240.png create mode 100644 third_party/jquery-ui/themes/start/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/start/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/start/theme.css create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-bg_diagonals-medium_20_d34d17_40x40.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-bg_gloss-wave_45_817865_500x100.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-bg_gloss-wave_60_fece2f_500x100.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-bg_gloss-wave_70_ffdd57_500x100.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-bg_gloss-wave_90_fff9e5_500x100.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-bg_highlight-soft_100_feeebd_1x100.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-bg_inset-soft_30_ffffff_1x100.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-icons_3d3d3d_256x240.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-icons_bd7b00_256x240.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-icons_d19405_256x240.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-icons_eb990f_256x240.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-icons_ed9f26_256x240.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-icons_fadc7a_256x240.png create mode 100644 third_party/jquery-ui/themes/sunny/images/ui-icons_ffe180_256x240.png create mode 100644 third_party/jquery-ui/themes/sunny/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/sunny/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/sunny/theme.css create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-bg_diamond_10_4f4221_10x8.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-bg_diamond_20_372806_10x8.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-bg_diamond_25_675423_10x8.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-bg_diamond_25_d5ac5d_10x8.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-bg_diamond_8_261803_10x8.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-bg_diamond_8_443113_10x8.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-bg_highlight-hard_65_fee4bd_1x100.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-icons_070603_256x240.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-icons_e8e2b5_256x240.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-icons_e9cd86_256x240.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-icons_efec9f_256x240.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-icons_f2ec64_256x240.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-icons_f9f2bd_256x240.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/images/ui-icons_ff7519_256x240.png create mode 100644 third_party/jquery-ui/themes/swanky-purse/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/swanky-purse/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/swanky-purse/theme.css create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-bg_diagonals-small_50_262626_40x40.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-bg_glass_40_0a0a0a_1x400.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-bg_glass_55_f1fbe5_1x400.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-bg_glass_60_000000_1x400.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-bg_gloss-wave_55_000000_500x100.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-bg_gloss-wave_85_9fda58_500x100.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-bg_gloss-wave_95_f6ecd5_500x100.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-icons_000000_256x240.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-icons_1f1f1f_256x240.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-icons_9fda58_256x240.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-icons_b8ec79_256x240.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-icons_cd0a0a_256x240.png create mode 100644 third_party/jquery-ui/themes/trontastic/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/trontastic/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/trontastic/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/trontastic/theme.css create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-bg_glass_20_555555_1x400.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-bg_glass_40_0078a3_1x400.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-bg_glass_40_ffc73d_1x400.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-bg_gloss-wave_25_333333_500x100.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-bg_highlight-soft_80_eeeeee_1x100.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-bg_inset-soft_25_000000_1x100.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-bg_inset-soft_30_f58400_1x100.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-icons_222222_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-icons_4b8e0b_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-icons_a83300_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-icons_cccccc_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-darkness/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/ui-darkness/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/ui-darkness/theme.css create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-icons_222222_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-icons_228ef1_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-icons_ef8c08_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-icons_ffd27a_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/images/ui-icons_ffffff_256x240.png create mode 100644 third_party/jquery-ui/themes/ui-lightness/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/ui-lightness/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/ui-lightness/theme.css create mode 100644 third_party/jquery-ui/themes/vader/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-bg_gloss-wave_16_121212_500x100.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-bg_highlight-hard_15_888888_1x100.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-bg_highlight-hard_55_555555_1x100.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-bg_highlight-soft_35_adadad_1x100.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-bg_highlight-soft_60_dddddd_1x100.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-bg_inset-soft_15_121212_1x100.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-icons_666666_256x240.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-icons_aaaaaa_256x240.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-icons_bbbbbb_256x240.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-icons_c98000_256x240.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-icons_cccccc_256x240.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-icons_cd0a0a_256x240.png create mode 100644 third_party/jquery-ui/themes/vader/images/ui-icons_f29a00_256x240.png create mode 100644 third_party/jquery-ui/themes/vader/jquery-ui.css create mode 100644 third_party/jquery-ui/themes/vader/jquery-ui.min.css create mode 100644 third_party/jquery-ui/themes/vader/theme.css create mode 100755 third_party/jquery-ui/ui/.jshintrc create mode 100644 third_party/jquery-ui/ui/core.js create mode 100644 third_party/jquery-ui/ui/data.js create mode 100644 third_party/jquery-ui/ui/disable-selection.js create mode 100644 third_party/jquery-ui/ui/effect.js create mode 100644 third_party/jquery-ui/ui/effects/effect-blind.js create mode 100644 third_party/jquery-ui/ui/effects/effect-bounce.js create mode 100644 third_party/jquery-ui/ui/effects/effect-clip.js create mode 100644 third_party/jquery-ui/ui/effects/effect-drop.js create mode 100644 third_party/jquery-ui/ui/effects/effect-explode.js create mode 100644 third_party/jquery-ui/ui/effects/effect-fade.js create mode 100644 third_party/jquery-ui/ui/effects/effect-fold.js create mode 100644 third_party/jquery-ui/ui/effects/effect-highlight.js create mode 100644 third_party/jquery-ui/ui/effects/effect-puff.js create mode 100644 third_party/jquery-ui/ui/effects/effect-pulsate.js create mode 100644 third_party/jquery-ui/ui/effects/effect-scale.js create mode 100644 third_party/jquery-ui/ui/effects/effect-shake.js create mode 100644 third_party/jquery-ui/ui/effects/effect-size.js create mode 100644 third_party/jquery-ui/ui/effects/effect-slide.js create mode 100644 third_party/jquery-ui/ui/effects/effect-transfer.js create mode 100644 third_party/jquery-ui/ui/escape-selector.js create mode 100644 third_party/jquery-ui/ui/focusable.js create mode 100644 third_party/jquery-ui/ui/form-reset-mixin.js create mode 100644 third_party/jquery-ui/ui/form.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-af.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ar-DZ.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ar.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-az.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-be.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-bg.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-bs.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ca.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-cs.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-cy-GB.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-da.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-de.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-el.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-en-AU.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-en-GB.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-en-NZ.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-eo.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-es.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-et.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-eu.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-fa.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-fi.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-fo.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-fr-CA.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-fr-CH.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-fr.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-gl.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-he.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-hi.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-hr.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-hu.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-hy.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-id.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-is.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-it-CH.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-it.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ja.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ka.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-kk.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-km.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ko.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ky.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-lb.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-lt.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-lv.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-mk.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ml.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ms.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-nb.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-nl-BE.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-nl.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-nn.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-no.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-pl.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-pt-BR.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-pt.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-rm.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ro.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ru.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-sk.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-sl.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-sq.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-sr-SR.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-sr.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-sv.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-ta.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-th.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-tj.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-tr.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-uk.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-vi.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-zh-CN.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-zh-HK.js create mode 100644 third_party/jquery-ui/ui/i18n/datepicker-zh-TW.js create mode 100644 third_party/jquery-ui/ui/ie.js create mode 100644 third_party/jquery-ui/ui/jquery-1-7.js create mode 100644 third_party/jquery-ui/ui/keycode.js create mode 100644 third_party/jquery-ui/ui/labels.js create mode 100644 third_party/jquery-ui/ui/minified/core.js create mode 100644 third_party/jquery-ui/ui/minified/data.js create mode 100644 third_party/jquery-ui/ui/minified/disable-selection.js create mode 100644 third_party/jquery-ui/ui/minified/effect.js create mode 100644 third_party/jquery-ui/ui/minified/escape-selector.js create mode 100644 third_party/jquery-ui/ui/minified/focusable.js create mode 100644 third_party/jquery-ui/ui/minified/form-reset-mixin.js create mode 100644 third_party/jquery-ui/ui/minified/form.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-af.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ar-DZ.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ar.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-az.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-be.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-bg.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-bs.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ca.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-cs.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-cy-GB.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-da.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-de.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-el.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-en-AU.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-en-GB.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-en-NZ.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-eo.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-es.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-et.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-eu.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-fa.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-fi.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-fo.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-fr-CA.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-fr-CH.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-fr.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-gl.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-he.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-hi.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-hr.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-hu.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-hy.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-id.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-is.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-it-CH.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-it.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ja.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ka.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-kk.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-km.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ko.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ky.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-lb.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-lt.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-lv.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-mk.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ml.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ms.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-nb.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-nl-BE.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-nl.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-nn.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-no.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-pl.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-pt-BR.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-pt.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-rm.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ro.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ru.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-sk.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-sl.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-sq.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-sr-SR.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-sr.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-sv.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-ta.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-th.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-tj.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-tr.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-uk.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-vi.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-zh-CN.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-zh-HK.js create mode 100644 third_party/jquery-ui/ui/minified/i18n/datepicker-zh-TW.js create mode 100644 third_party/jquery-ui/ui/minified/ie.js create mode 100644 third_party/jquery-ui/ui/minified/jquery-1-7.js create mode 100644 third_party/jquery-ui/ui/minified/keycode.js create mode 100644 third_party/jquery-ui/ui/minified/labels.js create mode 100644 third_party/jquery-ui/ui/minified/plugin.js create mode 100644 third_party/jquery-ui/ui/minified/position.js create mode 100644 third_party/jquery-ui/ui/minified/safe-active-element.js create mode 100644 third_party/jquery-ui/ui/minified/safe-blur.js create mode 100644 third_party/jquery-ui/ui/minified/scroll-parent.js create mode 100644 third_party/jquery-ui/ui/minified/tabbable.js create mode 100644 third_party/jquery-ui/ui/minified/unique-id.js create mode 100644 third_party/jquery-ui/ui/minified/version.js create mode 100644 third_party/jquery-ui/ui/minified/widget.js create mode 100644 third_party/jquery-ui/ui/plugin.js create mode 100644 third_party/jquery-ui/ui/position.js create mode 100644 third_party/jquery-ui/ui/safe-active-element.js create mode 100644 third_party/jquery-ui/ui/safe-blur.js create mode 100644 third_party/jquery-ui/ui/scroll-parent.js create mode 100644 third_party/jquery-ui/ui/tabbable.js create mode 100644 third_party/jquery-ui/ui/unique-id.js create mode 100644 third_party/jquery-ui/ui/version.js create mode 100644 third_party/jquery-ui/ui/widget.js create mode 100644 third_party/jquery-ui/ui/widgets/accordion.js create mode 100644 third_party/jquery-ui/ui/widgets/autocomplete.js create mode 100644 third_party/jquery-ui/ui/widgets/button.js create mode 100644 third_party/jquery-ui/ui/widgets/checkboxradio.js create mode 100644 third_party/jquery-ui/ui/widgets/controlgroup.js create mode 100644 third_party/jquery-ui/ui/widgets/datepicker.js create mode 100644 third_party/jquery-ui/ui/widgets/dialog.js create mode 100644 third_party/jquery-ui/ui/widgets/draggable.js create mode 100644 third_party/jquery-ui/ui/widgets/droppable.js create mode 100644 third_party/jquery-ui/ui/widgets/menu.js create mode 100644 third_party/jquery-ui/ui/widgets/mouse.js create mode 100644 third_party/jquery-ui/ui/widgets/progressbar.js create mode 100644 third_party/jquery-ui/ui/widgets/resizable.js create mode 100644 third_party/jquery-ui/ui/widgets/selectable.js create mode 100644 third_party/jquery-ui/ui/widgets/selectmenu.js create mode 100644 third_party/jquery-ui/ui/widgets/slider.js create mode 100644 third_party/jquery-ui/ui/widgets/sortable.js create mode 100644 third_party/jquery-ui/ui/widgets/spinner.js create mode 100644 third_party/jquery-ui/ui/widgets/tabs.js create mode 100644 third_party/jquery-ui/ui/widgets/tooltip.js diff --git a/.bowerrc b/.bowerrc deleted file mode 100644 index 44491d3..0000000 --- a/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "bower_components" -} diff --git a/app.yaml b/app.yaml index 555b562..c0031bf 100755 --- a/app.yaml +++ b/app.yaml @@ -17,59 +17,62 @@ api_version: 1 threadsafe: yes handlers: -# Testing -- url: /test - static_files: test/index.html - upload: test/index.html + # Testing + - url: /test + static_files: test/index.html + upload: test/index.html -# Tutorial -- url: /tutorial - static_dir: tutorial + # Tutorial + - url: /tutorial + static_dir: tutorial -- url: /tutorial - static_files: tutorial/index.html - upload: tutorial/index.html + - url: /tutorial + static_files: tutorial/index.html + upload: tutorial/index.html -# App Routing -- url: /favicon\.ico - static_files: favicon.ico - upload: favicon\.ico + # App Routing + - url: /favicon\.ico + static_files: favicon.ico + upload: favicon\.ico -- url: /robots.txt - static_files: robots.txt - upload: robots.txt + - url: /robots.txt + static_files: robots.txt + upload: robots.txt -- url: /app - static_dir: app + - url: /app + static_dir: app -- url: /bower_components - static_dir: bower_components + - url: /node_modules + static_dir: node_modules -- url: /css - static_dir: app/css + - url: /third_party + static_dir: third_party -- url: /img - static_dir: app/img + - url: /css + static_dir: app/css -- url: /js - static_dir: app/js + - url: /img + static_dir: app/img -- url: /partials - static_dir: app/partials + - url: /js + static_dir: app/js -- url: .* - script: main.app + - url: /partials + static_dir: app/partials + + - url: .* + script: main.app # Libraries libraries: -- name: webapp2 - version: "2.5.2" + - name: webapp2 + version: "2.5.2" -- name: jinja2 - version: latest + - name: jinja2 + version: latest -- name: pycrypto - version: "2.6" + - name: pycrypto + version: "2.6" # Don't Upload skip_files: | diff --git a/package-lock.json b/package-lock.json index fca5869..71fd90e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,6 +64,11 @@ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" }, + "jquery-ui": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz", + "integrity": "sha1-vLQEXI3QU5wTS8FIjN0+dop6nlE=" + }, "js-throttle-debounce": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/js-throttle-debounce/-/js-throttle-debounce-0.1.1.tgz", diff --git a/package.json b/package.json index 6443a19..9fd8003 100644 --- a/package.json +++ b/package.json @@ -12,15 +12,14 @@ "angular": "~1.4.5", "angular-animate": "~1.4.5", "angular-aria": "~1.4.5", + "angular-environment": "^1.0.8", + "angular-local-storage": "^0.7.1", "angular-material": "~0.11.0", "angular-resource": "~1.4.5", "angular-route": "~1.4.5", "angularytics": "0.3.0", "hammerjs": "~2.0.4", "jquery": "^3.1.1", - "angular-environment": "^1.0.8", - "angular-local-storage": "^0.7.1", - "angular-ui-sortable": "^0.17.1", "js-throttle-debounce": "^0.1.1" }, "devDependencies": { diff --git a/templates/index.html b/templates/index.html index 23650db..a6555a5 100755 --- a/templates/index.html +++ b/templates/index.html @@ -1,58 +1,62 @@ - - - - - - - - Direct - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + Direct + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/third_party/angular-ui-sortable/.bower.json b/third_party/angular-ui-sortable/.bower.json new file mode 100644 index 0000000..5da69ab --- /dev/null +++ b/third_party/angular-ui-sortable/.bower.json @@ -0,0 +1,22 @@ +{ + "name": "angular-ui-sortable", + "version": "0.17.2", + "main": [ + "./sortable.js" + ], + "dependencies": { + "angular": ">=1.2.x", + "jquery": ">=3.1.x", + "jquery-ui": ">=1.12.x" + }, + "homepage": "https://github.com/angular-ui/ui-sortable", + "_release": "0.17.2", + "_resolution": { + "type": "version", + "tag": "v0.17.2", + "commit": "017fbd3f911576914915aa3dd08022c83b7fd3a3" + }, + "_source": "https://github.com/angular-ui/ui-sortable.git", + "_target": "^0.17.1", + "_originalSource": "angular-ui-sortable" +} \ No newline at end of file diff --git a/third_party/angular-ui-sortable/.travis.yml b/third_party/angular-ui-sortable/.travis.yml new file mode 100644 index 0000000..8c4c2c4 --- /dev/null +++ b/third_party/angular-ui-sortable/.travis.yml @@ -0,0 +1,5 @@ +--- +# blacklist the bower branch +branches: + only: + - master diff --git a/third_party/angular-ui-sortable/bower.json b/third_party/angular-ui-sortable/bower.json new file mode 100644 index 0000000..6c2ffc2 --- /dev/null +++ b/third_party/angular-ui-sortable/bower.json @@ -0,0 +1,10 @@ +{ + "name": "angular-ui-sortable", + "version": "0.17.2", + "main": ["./sortable.js"], + "dependencies": { + "angular": ">=1.2.x", + "jquery": ">=3.1.x", + "jquery-ui": ">=1.12.x" + } +} diff --git a/third_party/angular-ui-sortable/sortable.js b/third_party/angular-ui-sortable/sortable.js new file mode 100644 index 0000000..0eb5719 --- /dev/null +++ b/third_party/angular-ui-sortable/sortable.js @@ -0,0 +1,567 @@ +/** + * angular-ui-sortable - This directive allows you to jQueryUI Sortable. + * @version v0.17.2 - 2017-08-17 + * @link http://angular-ui.github.com + * @license MIT + */ + +(function(window, angular, undefined) { +'use strict'; +/* + jQuery UI Sortable plugin wrapper + + @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config + */ +angular.module('ui.sortable', []) + .value('uiSortableConfig',{ + // the default for jquery-ui sortable is "> *", we need to restrict this to + // ng-repeat items + // if the user uses + items: '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]' + }) + .directive('uiSortable', [ + 'uiSortableConfig', '$timeout', '$log', + function(uiSortableConfig, $timeout, $log) { + return { + require:'?ngModel', + scope: { + ngModel:'=', + uiSortable:'=', + ////Expression bindings from html. + create:'&uiSortableCreate', + // helper:'&uiSortableHelper', + start:'&uiSortableStart', + activate:'&uiSortableActivate', + // sort:'&uiSortableSort', + // change:'&uiSortableChange', + // over:'&uiSortableOver', + // out:'&uiSortableOut', + beforeStop:'&uiSortableBeforeStop', + update:'&uiSortableUpdate', + remove:'&uiSortableRemove', + receive:'&uiSortableReceive', + deactivate:'&uiSortableDeactivate', + stop:'&uiSortableStop' + }, + link: function(scope, element, attrs, ngModel) { + var savedNodes; + var helper; + + function combineCallbacks(first, second){ + var firstIsFunc = typeof first === 'function'; + var secondIsFunc = typeof second === 'function'; + if(firstIsFunc && secondIsFunc) { + return function() { + first.apply(this, arguments); + second.apply(this, arguments); + }; + } else if (secondIsFunc) { + return second; + } + return first; + } + + function getSortableWidgetInstance(element) { + // this is a fix to support jquery-ui prior to v1.11.x + // otherwise we should be using `element.sortable('instance')` + var data = element.data('ui-sortable'); + if (data && typeof data === 'object' && data.widgetFullName === 'ui-sortable') { + return data; + } + return null; + } + + function patchSortableOption(key, value) { + if (callbacks[key]) { + if( key === 'stop' ){ + // call apply after stop + value = combineCallbacks( + value, function() { scope.$apply(); }); + + value = combineCallbacks(value, afterStop); + } + // wrap the callback + value = combineCallbacks(callbacks[key], value); + } else if (wrappers[key]) { + value = wrappers[key](value); + } + + // patch the options that need to have values set + if (!value && (key === 'items' || key === 'ui-model-items')) { + value = uiSortableConfig.items; + } + + return value; + } + + function patchUISortableOptions(newVal, oldVal, sortableWidgetInstance) { + function addDummyOptionKey(value, key) { + if (!(key in opts)) { + // add the key in the opts object so that + // the patch function detects and handles it + opts[key] = null; + } + } + // for this directive to work we have to attach some callbacks + angular.forEach(callbacks, addDummyOptionKey); + + // only initialize it in case we have to + // update some options of the sortable + var optsDiff = null; + + if (oldVal) { + // reset deleted options to default + var defaultOptions; + angular.forEach(oldVal, function(oldValue, key) { + if (!newVal || !(key in newVal)) { + if (key in directiveOpts) { + if (key === 'ui-floating') { + opts[key] = 'auto'; + } else { + opts[key] = patchSortableOption(key, undefined); + } + return; + } + + if (!defaultOptions) { + defaultOptions = angular.element.ui.sortable().options; + } + var defaultValue = defaultOptions[key]; + defaultValue = patchSortableOption(key, defaultValue); + + if (!optsDiff) { + optsDiff = {}; + } + optsDiff[key] = defaultValue; + opts[key] = defaultValue; + } + }); + } + + // update changed options + angular.forEach(newVal, function(value, key) { + // if it's a custom option of the directive, + // handle it approprietly + if (key in directiveOpts) { + if (key === 'ui-floating' && (value === false || value === true) && sortableWidgetInstance) { + sortableWidgetInstance.floating = value; + } + + opts[key] = patchSortableOption(key, value); + return; + } + + value = patchSortableOption(key, value); + + if (!optsDiff) { + optsDiff = {}; + } + optsDiff[key] = value; + opts[key] = value; + }); + + return optsDiff; + } + + function getPlaceholderElement (element) { + var placeholder = element.sortable('option','placeholder'); + + // placeholder.element will be a function if the placeholder, has + // been created (placeholder will be an object). If it hasn't + // been created, either placeholder will be false if no + // placeholder class was given or placeholder.element will be + // undefined if a class was given (placeholder will be a string) + if (placeholder && placeholder.element && typeof placeholder.element === 'function') { + var result = placeholder.element(); + // workaround for jquery ui 1.9.x, + // not returning jquery collection + result = angular.element(result); + return result; + } + return null; + } + + function getPlaceholderExcludesludes (element, placeholder) { + // exact match with the placeholder's class attribute to handle + // the case that multiple connected sortables exist and + // the placeholder option equals the class of sortable items + var notCssSelector = opts['ui-model-items'].replace(/[^,]*>/g, ''); + var excludes = element.find('[class="' + placeholder.attr('class') + '"]:not(' + notCssSelector + ')'); + return excludes; + } + + function hasSortingHelper (element, ui) { + var helperOption = element.sortable('option','helper'); + return helperOption === 'clone' || (typeof helperOption === 'function' && ui.item.sortable.isCustomHelperUsed()); + } + + function getSortingHelper (element, ui/*, savedNodes*/) { + var result = null; + if (hasSortingHelper(element, ui) && + element.sortable( 'option', 'appendTo' ) === 'parent') { + // The .ui-sortable-helper element (that's the default class name) + result = helper; + } + return result; + } + + // thanks jquery-ui + function isFloating (item) { + return (/left|right/).test(item.css('float')) || (/inline|table-cell/).test(item.css('display')); + } + + function getElementContext(elementScopes, element) { + for (var i = 0; i < elementScopes.length; i++) { + var c = elementScopes[i]; + if (c.element[0] === element[0]) { + return c; + } + } + } + + function afterStop(e, ui) { + ui.item.sortable._destroy(); + } + + // return the index of ui.item among the items + // we can't just do ui.item.index() because there it might have siblings + // which are not items + function getItemIndex(item) { + return item.parent() + .find(opts['ui-model-items']) + .index(item); + } + + var opts = {}; + + // directive specific options + var directiveOpts = { + 'ui-floating': undefined, + 'ui-model-items': uiSortableConfig.items + }; + + var callbacks = { + create: null, + start: null, + activate: null, + // sort: null, + // change: null, + // over: null, + // out: null, + beforeStop: null, + update: null, + remove: null, + receive: null, + deactivate: null, + stop: null + }; + + var wrappers = { + helper: null + }; + + angular.extend(opts, directiveOpts, uiSortableConfig, scope.uiSortable); + + if (!angular.element.fn || !angular.element.fn.jquery) { + $log.error('ui.sortable: jQuery should be included before AngularJS!'); + return; + } + + function wireUp () { + // When we add or remove elements, we need the sortable to 'refresh' + // so it can find the new/removed elements. + scope.$watchCollection('ngModel', function() { + // Timeout to let ng-repeat modify the DOM + $timeout(function() { + // ensure that the jquery-ui-sortable widget instance + // is still bound to the directive's element + if (!!getSortableWidgetInstance(element)) { + element.sortable('refresh'); + } + }, 0, false); + }); + + callbacks.start = function(e, ui) { + if (opts['ui-floating'] === 'auto') { + // since the drag has started, the element will be + // absolutely positioned, so we check its siblings + var siblings = ui.item.siblings(); + var sortableWidgetInstance = getSortableWidgetInstance(angular.element(e.target)); + sortableWidgetInstance.floating = isFloating(siblings); + } + + // Save the starting position of dragged item + var index = getItemIndex(ui.item); + ui.item.sortable = { + model: ngModel.$modelValue[index], + index: index, + source: element, + sourceList: ui.item.parent(), + sourceModel: ngModel.$modelValue, + cancel: function () { + ui.item.sortable._isCanceled = true; + }, + isCanceled: function () { + return ui.item.sortable._isCanceled; + }, + isCustomHelperUsed: function () { + return !!ui.item.sortable._isCustomHelperUsed; + }, + _isCanceled: false, + _isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed, + _destroy: function () { + angular.forEach(ui.item.sortable, function(value, key) { + ui.item.sortable[key] = undefined; + }); + }, + _connectedSortables: [], + _getElementContext: function (element) { + return getElementContext(this._connectedSortables, element); + } + }; + }; + + callbacks.activate = function(e, ui) { + var isSourceContext = ui.item.sortable.source === element; + var savedNodesOrigin = isSourceContext ? + ui.item.sortable.sourceList : + element; + var elementContext = { + element: element, + scope: scope, + isSourceContext: isSourceContext, + savedNodesOrigin: savedNodesOrigin + }; + // save the directive's scope so that it is accessible from ui.item.sortable + ui.item.sortable._connectedSortables.push(elementContext); + + // We need to make a copy of the current element's contents so + // we can restore it after sortable has messed it up. + // This is inside activate (instead of start) in order to save + // both lists when dragging between connected lists. + savedNodes = savedNodesOrigin.contents(); + helper = ui.helper; + + // If this list has a placeholder (the connected lists won't), + // don't inlcude it in saved nodes. + var placeholder = getPlaceholderElement(element); + if (placeholder && placeholder.length) { + var excludes = getPlaceholderExcludesludes(element, placeholder); + savedNodes = savedNodes.not(excludes); + } + }; + + callbacks.update = function(e, ui) { + // Save current drop position but only if this is not a second + // update that happens when moving between lists because then + // the value will be overwritten with the old value + if (!ui.item.sortable.received) { + ui.item.sortable.dropindex = getItemIndex(ui.item); + var droptarget = ui.item.parent().closest('[ui-sortable], [data-ui-sortable], [x-ui-sortable]'); + ui.item.sortable.droptarget = droptarget; + ui.item.sortable.droptargetList = ui.item.parent(); + + var droptargetContext = ui.item.sortable._getElementContext(droptarget); + ui.item.sortable.droptargetModel = droptargetContext.scope.ngModel; + + // Cancel the sort (let ng-repeat do the sort for us) + // Don't cancel if this is the received list because it has + // already been canceled in the other list, and trying to cancel + // here will mess up the DOM. + element.sortable('cancel'); + } + + // Put the nodes back exactly the way they started (this is very + // important because ng-repeat uses comment elements to delineate + // the start and stop of repeat sections and sortable doesn't + // respect their order (even if we cancel, the order of the + // comments are still messed up). + var sortingHelper = !ui.item.sortable.received && getSortingHelper(element, ui, savedNodes); + if (sortingHelper && sortingHelper.length) { + // Restore all the savedNodes except from the sorting helper element. + // That way it will be garbage collected. + savedNodes = savedNodes.not(sortingHelper); + } + var elementContext = ui.item.sortable._getElementContext(element); + savedNodes.appendTo(elementContext.savedNodesOrigin); + + // If this is the target connected list then + // it's safe to clear the restored nodes since: + // update is currently running and + // stop is not called for the target list. + if (ui.item.sortable.received) { + savedNodes = null; + } + + // If received is true (an item was dropped in from another list) + // then we add the new item to this list otherwise wait until the + // stop event where we will know if it was a sort or item was + // moved here from another list + if (ui.item.sortable.received && !ui.item.sortable.isCanceled()) { + scope.$apply(function () { + ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0, + ui.item.sortable.moved); + }); + scope.$emit('ui-sortable:moved', ui); + } + }; + + callbacks.stop = function(e, ui) { + // If the received flag hasn't be set on the item, this is a + // normal sort, if dropindex is set, the item was moved, so move + // the items in the list. + var wasMoved = ('dropindex' in ui.item.sortable) && + !ui.item.sortable.isCanceled(); + + if (wasMoved && !ui.item.sortable.received) { + + scope.$apply(function () { + ngModel.$modelValue.splice( + ui.item.sortable.dropindex, 0, + ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]); + }); + scope.$emit('ui-sortable:moved', ui); + } else if (!wasMoved && + !angular.equals(element.contents().toArray(), savedNodes.toArray())) { + // if the item was not moved + // and the DOM element order has changed, + // then restore the elements + // so that the ngRepeat's comment are correct. + + var sortingHelper = getSortingHelper(element, ui, savedNodes); + if (sortingHelper && sortingHelper.length) { + // Restore all the savedNodes except from the sorting helper element. + // That way it will be garbage collected. + savedNodes = savedNodes.not(sortingHelper); + } + var elementContext = ui.item.sortable._getElementContext(element); + savedNodes.appendTo(elementContext.savedNodesOrigin); + } + + // It's now safe to clear the savedNodes and helper + // since stop is the last callback. + savedNodes = null; + helper = null; + }; + + callbacks.receive = function(e, ui) { + // An item was dropped here from another list, set a flag on the + // item. + ui.item.sortable.received = true; + }; + + callbacks.remove = function(e, ui) { + // Workaround for a problem observed in nested connected lists. + // There should be an 'update' event before 'remove' when moving + // elements. If the event did not fire, cancel sorting. + if (!('dropindex' in ui.item.sortable)) { + element.sortable('cancel'); + ui.item.sortable.cancel(); + } + + // Remove the item from this list's model and copy data into item, + // so the next list can retrive it + if (!ui.item.sortable.isCanceled()) { + scope.$apply(function () { + ui.item.sortable.moved = ngModel.$modelValue.splice( + ui.item.sortable.index, 1)[0]; + }); + } + }; + + // setup attribute handlers + angular.forEach(callbacks, function(value, key) { + callbacks[key] = combineCallbacks(callbacks[key], + function () { + var attrHandler = scope[key]; + var attrHandlerFn; + if (typeof attrHandler === 'function' && + ('uiSortable' + key.substring(0,1).toUpperCase() + key.substring(1)).length && + typeof (attrHandlerFn = attrHandler()) === 'function') { + attrHandlerFn.apply(this, arguments); + } + }); + }); + + + wrappers.helper = function (inner) { + if (inner && typeof inner === 'function') { + return function (e, item) { + var oldItemSortable = item.sortable; + var index = getItemIndex(item); + item.sortable = { + model: ngModel.$modelValue[index], + index: index, + source: element, + sourceList: item.parent(), + sourceModel: ngModel.$modelValue, + _restore: function () { + angular.forEach(item.sortable, function(value, key) { + item.sortable[key] = undefined; + }); + + item.sortable = oldItemSortable; + } + }; + + var innerResult = inner.apply(this, arguments); + item.sortable._restore(); + item.sortable._isCustomHelperUsed = item !== innerResult; + return innerResult; + }; + } + return inner; + }; + + scope.$watchCollection('uiSortable', function(newVal, oldVal) { + // ensure that the jquery-ui-sortable widget instance + // is still bound to the directive's element + var sortableWidgetInstance = getSortableWidgetInstance(element); + if (!!sortableWidgetInstance) { + var optsDiff = patchUISortableOptions(newVal, oldVal, sortableWidgetInstance); + + if (optsDiff) { + element.sortable('option', optsDiff); + } + } + }, true); + + patchUISortableOptions(opts); + } + + function init () { + if (ngModel) { + wireUp(); + } else { + $log.info('ui.sortable: ngModel not provided!', element); + } + + // Create sortable + element.sortable(opts); + } + + function initIfEnabled () { + if (scope.uiSortable && scope.uiSortable.disabled) { + return false; + } + + init(); + + // Stop Watcher + initIfEnabled.cancelWatcher(); + initIfEnabled.cancelWatcher = angular.noop; + + return true; + } + + initIfEnabled.cancelWatcher = angular.noop; + + if (!initIfEnabled()) { + initIfEnabled.cancelWatcher = scope.$watch('uiSortable.disabled', initIfEnabled); + } + } + }; + } + ]); + +})(window, window.angular); diff --git a/third_party/angular-ui-sortable/sortable.min.js b/third_party/angular-ui-sortable/sortable.min.js new file mode 100644 index 0000000..1e1753b --- /dev/null +++ b/third_party/angular-ui-sortable/sortable.min.js @@ -0,0 +1,8 @@ +/** + * angular-ui-sortable - This directive allows you to jQueryUI Sortable. + * @version v0.17.2 - 2017-08-17 + * @link http://angular-ui.github.com + * @license MIT + */ + +!function(a,b,c){"use strict";b.module("ui.sortable",[]).value("uiSortableConfig",{items:"> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]"}).directive("uiSortable",["uiSortableConfig","$timeout","$log",function(a,d,e){return{require:"?ngModel",scope:{ngModel:"=",uiSortable:"=",create:"&uiSortableCreate",start:"&uiSortableStart",activate:"&uiSortableActivate",beforeStop:"&uiSortableBeforeStop",update:"&uiSortableUpdate",remove:"&uiSortableRemove",receive:"&uiSortableReceive",deactivate:"&uiSortableDeactivate",stop:"&uiSortableStop"},link:function(f,g,h,i){function j(a,b){var c="function"==typeof a,d="function"==typeof b;return c&&d?function(){a.apply(this,arguments),b.apply(this,arguments)}:d?b:a}function k(a){var b=a.data("ui-sortable");return b&&"object"==typeof b&&"ui-sortable"===b.widgetFullName?b:null}function l(b,c){return C[b]?("stop"===b&&(c=j(c,function(){f.$apply()}),c=j(c,t)),c=j(C[b],c)):D[b]&&(c=D[b](c)),c||"items"!==b&&"ui-model-items"!==b||(c=a.items),c}function m(a,d,e){function f(a,b){b in A||(A[b]=null)}b.forEach(C,f);var g=null;if(d){var h;b.forEach(d,function(d,e){if(!(a&&e in a)){if(e in B)return void("ui-floating"===e?A[e]="auto":A[e]=l(e,c));h||(h=b.element.ui.sortable().options);var f=h[e];f=l(e,f),g||(g={}),g[e]=f,A[e]=f}})}return b.forEach(a,function(a,b){return b in B?("ui-floating"!==b||a!==!1&&a!==!0||!e||(e.floating=a),void(A[b]=l(b,a))):(a=l(b,a),g||(g={}),g[b]=a,void(A[b]=a))}),g}function n(a){var c=a.sortable("option","placeholder");if(c&&c.element&&"function"==typeof c.element){var d=c.element();return d=b.element(d)}return null}function o(a,b){var c=A["ui-model-items"].replace(/[^,]*>/g,""),d=a.find('[class="'+b.attr("class")+'"]:not('+c+")");return d}function p(a,b){var c=a.sortable("option","helper");return"clone"===c||"function"==typeof c&&b.item.sortable.isCustomHelperUsed()}function q(a,b){var c=null;return p(a,b)&&"parent"===a.sortable("option","appendTo")&&(c=z),c}function r(a){return/left|right/.test(a.css("float"))||/inline|table-cell/.test(a.css("display"))}function s(a,b){for(var c=0;c=1.6" + }, + "homepage": "https://github.com/components/jqueryui", + "_release": "1.12.1", + "_resolution": { + "type": "version", + "tag": "1.12.1", + "commit": "44ecf3794cc56b65954cc19737234a3119d036cc" + }, + "_source": "https://github.com/components/jqueryui.git", + "_target": ">=1.12.x", + "_originalSource": "jquery-ui" +} \ No newline at end of file diff --git a/third_party/jquery-ui/.gitignore b/third_party/jquery-ui/.gitignore new file mode 100644 index 0000000..cfcaf7a --- /dev/null +++ b/third_party/jquery-ui/.gitignore @@ -0,0 +1,4 @@ +components +composer.lock +vendor +.DS_Store diff --git a/third_party/jquery-ui/README.md b/third_party/jquery-ui/README.md new file mode 100644 index 0000000..749a76e --- /dev/null +++ b/third_party/jquery-ui/README.md @@ -0,0 +1,12 @@ +jQuery UI +========= + +Shim [repository](https://github.com/components/jqueryui) for the [jQuery UI](https://jqueryui.com). + +Package Managers +---------------- + +* [Bower](http://bower.io/): `jquery-ui` +* [Component](https://github.com/component/component): `components/jquery-ui` +* [Composer](http://packagist.org/packages/components/jquery): `components/jqueryui` +* [npm](https://www.npmjs.com/): `components-jqueryui` \ No newline at end of file diff --git a/third_party/jquery-ui/bower.json b/third_party/jquery-ui/bower.json new file mode 100644 index 0000000..965aba7 --- /dev/null +++ b/third_party/jquery-ui/bower.json @@ -0,0 +1,13 @@ +{ + "name": "jquery-ui", + "version": "1.12.1", + "main": [ + "jquery-ui.js" + ], + "ignore": [ + ], + "license": "MIT", + "dependencies": { + "jquery": ">=1.6" + } +} diff --git a/third_party/jquery-ui/component.json b/third_party/jquery-ui/component.json new file mode 100644 index 0000000..25188ae --- /dev/null +++ b/third_party/jquery-ui/component.json @@ -0,0 +1,13 @@ +{ + "name": "jquery-ui", + "repo": "components/jqueryui", + "version": "1.12.1", + "license": "MIT", + "scripts": [ + "jquery-ui.js" + ], + "main": "jquery-ui.js", + "dependencies": { + "components/jquery": "*" + } +} diff --git a/third_party/jquery-ui/composer.json b/third_party/jquery-ui/composer.json new file mode 100644 index 0000000..cea9ab6 --- /dev/null +++ b/third_party/jquery-ui/composer.json @@ -0,0 +1,69 @@ +{ + "name": "components/jqueryui", + "type": "component", + "description": "jQuery UI is a curated set of user interface interactions, effects, widgets, and themes built on top of the jQuery JavaScript Library. Whether you're building highly interactive web applications or you just need to add a date picker to a form control, jQuery UI is the perfect choice.", + "license": "MIT", + "require": { + "components/jquery": ">=1.6" + }, + "authors": [ + { + "name": "jQuery UI Team", + "homepage": "http://jqueryui.com/about" + }, + { + "name": "Scott Gonzalez", + "email": "scott.gonzalez@gmail.com", + "homepage": "http://scottgonzalez.com" + }, + { + "name": "Joern Zaefferer", + "email": "joern.zaefferer@gmail.com", + "homepage": "http://bassistance.de" + }, + { + "name": "Kris Borchers", + "email": "kris.borchers@gmail.com", + "homepage": "http://krisborchers.com" + }, + { + "name": "Corey Frang", + "email": "gnarf37@gmail.com", + "homepage": "http://gnarf.net" + }, + { + "name": "Mike Sherov", + "email": "mike.sherov@gmail.com", + "homepage": "http://mike.sherov.com" + }, + { + "name": "TJ VanToll", + "email": "tj.vantoll@gmail.com", + "homepage": "http://tjvantoll.com" + }, + { + "name": "Felix Nagel", + "email": "info@felixnagel.com", + "homepage": "http://www.felixnagel.com" + } + ], + "extra": { + "component": { + "name": "jquery-ui", + "scripts": [ + "jquery-ui.js" + ], + "files": [ + "ui/**", + "themes/**", + "jquery-ui.min.js" + ], + "shim": { + "deps": [ + "jquery" + ], + "exports": "jQuery" + } + } + } +} diff --git a/third_party/jquery-ui/jquery-ui.js b/third_party/jquery-ui/jquery-ui.js new file mode 100644 index 0000000..0213552 --- /dev/null +++ b/third_party/jquery-ui/jquery-ui.js @@ -0,0 +1,18706 @@ +/*! jQuery UI - v1.12.1 - 2016-09-14 +* http://jqueryui.com +* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define([ "jquery" ], factory ); + } else { + + // Browser globals + factory( jQuery ); + } +}(function( $ ) { + +$.ui = $.ui || {}; + +var version = $.ui.version = "1.12.1"; + + +/*! + * jQuery UI Widget 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Widget +//>>group: Core +//>>description: Provides a factory for creating stateful widgets with a common API. +//>>docs: http://api.jqueryui.com/jQuery.widget/ +//>>demos: http://jqueryui.com/widget/ + + + +var widgetUuid = 0; +var widgetSlice = Array.prototype.slice; + +$.cleanData = ( function( orig ) { + return function( elems ) { + var events, elem, i; + for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { + try { + + // Only trigger remove when necessary to save time + events = $._data( elem, "events" ); + if ( events && events.remove ) { + $( elem ).triggerHandler( "remove" ); + } + + // Http://bugs.jquery.com/ticket/8235 + } catch ( e ) {} + } + orig( elems ); + }; +} )( $.cleanData ); + +$.widget = function( name, base, prototype ) { + var existingConstructor, constructor, basePrototype; + + // ProxiedPrototype allows the provided prototype to remain unmodified + // so that it can be used as a mixin for multiple widgets (#8876) + var proxiedPrototype = {}; + + var namespace = name.split( "." )[ 0 ]; + name = name.split( "." )[ 1 ]; + var fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + if ( $.isArray( prototype ) ) { + prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); + } + + // Create selector for plugin + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { + return !!$.data( elem, fullName ); + }; + + $[ namespace ] = $[ namespace ] || {}; + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { + + // Allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new constructor( options, element ); + } + + // Allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + + // Extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, + + // Copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), + + // Track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + } ); + + basePrototype = new base(); + + // We need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend( {}, basePrototype.options ); + $.each( prototype, function( prop, value ) { + if ( !$.isFunction( value ) ) { + proxiedPrototype[ prop ] = value; + return; + } + proxiedPrototype[ prop ] = ( function() { + function _super() { + return base.prototype[ prop ].apply( this, arguments ); + } + + function _superApply( args ) { + return base.prototype[ prop ].apply( this, args ); + } + + return function() { + var __super = this._super; + var __superApply = this._superApply; + var returnValue; + + this._super = _super; + this._superApply = _superApply; + + returnValue = value.apply( this, arguments ); + + this._super = __super; + this._superApply = __superApply; + + return returnValue; + }; + } )(); + } ); + constructor.prototype = $.widget.extend( basePrototype, { + + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name + }, proxiedPrototype, { + constructor: constructor, + namespace: namespace, + widgetName: name, + widgetFullName: fullName + } ); + + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; + + // Redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, + child._proto ); + } ); + + // Remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } + + $.widget.bridge( name, constructor ); + + return constructor; +}; + +$.widget.extend = function( target ) { + var input = widgetSlice.call( arguments, 1 ); + var inputIndex = 0; + var inputLength = input.length; + var key; + var value; + + for ( ; inputIndex < inputLength; inputIndex++ ) { + for ( key in input[ inputIndex ] ) { + value = input[ inputIndex ][ key ]; + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { + + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : + + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); + + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; +}; + +$.widget.bridge = function( name, object ) { + var fullName = object.prototype.widgetFullName || name; + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string"; + var args = widgetSlice.call( arguments, 1 ); + var returnValue = this; + + if ( isMethodCall ) { + + // If this is an empty collection, we need to have the instance method + // return undefined instead of the jQuery instance + if ( !this.length && options === "instance" ) { + returnValue = undefined; + } else { + this.each( function() { + var methodValue; + var instance = $.data( this, fullName ); + + if ( options === "instance" ) { + returnValue = instance; + return false; + } + + if ( !instance ) { + return $.error( "cannot call methods on " + name + + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } + + if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for " + name + + " widget instance" ); + } + + methodValue = instance[ options ].apply( instance, args ); + + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; + return false; + } + } ); + } + } else { + + // Allow multiple hashes to be passed on init + if ( args.length ) { + options = $.widget.extend.apply( null, [ options ].concat( args ) ); + } + + this.each( function() { + var instance = $.data( this, fullName ); + if ( instance ) { + instance.option( options || {} ); + if ( instance._init ) { + instance._init(); + } + } else { + $.data( this, fullName, new object( options, this ) ); + } + } ); + } + + return returnValue; + }; +}; + +$.Widget = function( /* options, element */ ) {}; +$.Widget._childConstructors = []; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "
", + + options: { + classes: {}, + disabled: false, + + // Callbacks + create: null + }, + + _createWidget: function( options, element ) { + element = $( element || this.defaultElement || this )[ 0 ]; + this.element = $( element ); + this.uuid = widgetUuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + this.classesElementLookup = {}; + + if ( element !== this ) { + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + } ); + this.document = $( element.style ? + + // Element within the document + element.ownerDocument : + + // Element is window or document + element.document || element ); + this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); + } + + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + + this._create(); + + if ( this.options.disabled ) { + this._setOptionDisabled( this.options.disabled ); + } + + this._trigger( "create", null, this._getCreateEventData() ); + this._init(); + }, + + _getCreateOptions: function() { + return {}; + }, + + _getCreateEventData: $.noop, + + _create: $.noop, + + _init: $.noop, + + destroy: function() { + var that = this; + + this._destroy(); + $.each( this.classesElementLookup, function( key, value ) { + that._removeClass( value, key ); + } ); + + // We can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .off( this.eventNamespace ) + .removeData( this.widgetFullName ); + this.widget() + .off( this.eventNamespace ) + .removeAttr( "aria-disabled" ); + + // Clean up events and states + this.bindings.off( this.eventNamespace ); + }, + + _destroy: $.noop, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key; + var parts; + var curOption; + var i; + + if ( arguments.length === 0 ) { + + // Don't return a reference to the internal hash + return $.widget.extend( {}, this.options ); + } + + if ( typeof key === "string" ) { + + // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( arguments.length === 1 ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( arguments.length === 1 ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions( options ); + + return this; + }, + + _setOptions: function( options ) { + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } + + return this; + }, + + _setOption: function( key, value ) { + if ( key === "classes" ) { + this._setOptionClasses( value ); + } + + this.options[ key ] = value; + + if ( key === "disabled" ) { + this._setOptionDisabled( value ); + } + + return this; + }, + + _setOptionClasses: function( value ) { + var classKey, elements, currentElements; + + for ( classKey in value ) { + currentElements = this.classesElementLookup[ classKey ]; + if ( value[ classKey ] === this.options.classes[ classKey ] || + !currentElements || + !currentElements.length ) { + continue; + } + + // We are doing this to create a new jQuery object because the _removeClass() call + // on the next line is going to destroy the reference to the current elements being + // tracked. We need to save a copy of this collection so that we can add the new classes + // below. + elements = $( currentElements.get() ); + this._removeClass( currentElements, classKey ); + + // We don't use _addClass() here, because that uses this.options.classes + // for generating the string of classes. We want to use the value passed in from + // _setOption(), this is the new value of the classes option which was passed to + // _setOption(). We pass this value directly to _classes(). + elements.addClass( this._classes( { + element: elements, + keys: classKey, + classes: value, + add: true + } ) ); + } + }, + + _setOptionDisabled: function( value ) { + this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); + + // If the widget is becoming disabled, then nothing is interactive + if ( value ) { + this._removeClass( this.hoverable, null, "ui-state-hover" ); + this._removeClass( this.focusable, null, "ui-state-focus" ); + } + }, + + enable: function() { + return this._setOptions( { disabled: false } ); + }, + + disable: function() { + return this._setOptions( { disabled: true } ); + }, + + _classes: function( options ) { + var full = []; + var that = this; + + options = $.extend( { + element: this.element, + classes: this.options.classes || {} + }, options ); + + function processClassString( classes, checkOption ) { + var current, i; + for ( i = 0; i < classes.length; i++ ) { + current = that.classesElementLookup[ classes[ i ] ] || $(); + if ( options.add ) { + current = $( $.unique( current.get().concat( options.element.get() ) ) ); + } else { + current = $( current.not( options.element ).get() ); + } + that.classesElementLookup[ classes[ i ] ] = current; + full.push( classes[ i ] ); + if ( checkOption && options.classes[ classes[ i ] ] ) { + full.push( options.classes[ classes[ i ] ] ); + } + } + } + + this._on( options.element, { + "remove": "_untrackClassesElement" + } ); + + if ( options.keys ) { + processClassString( options.keys.match( /\S+/g ) || [], true ); + } + if ( options.extra ) { + processClassString( options.extra.match( /\S+/g ) || [] ); + } + + return full.join( " " ); + }, + + _untrackClassesElement: function( event ) { + var that = this; + $.each( that.classesElementLookup, function( key, value ) { + if ( $.inArray( event.target, value ) !== -1 ) { + that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); + } + } ); + }, + + _removeClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, false ); + }, + + _addClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, true ); + }, + + _toggleClass: function( element, keys, extra, add ) { + add = ( typeof add === "boolean" ) ? add : extra; + var shift = ( typeof element === "string" || element === null ), + options = { + extra: shift ? keys : extra, + keys: shift ? element : keys, + element: shift ? this.element : element, + add: add + }; + options.element.toggleClass( this._classes( options ), add ); + return this; + }, + + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement; + var instance = this; + + // No suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // No element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + + // Allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // Copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^([\w:-]*)\s*(.*)$/ ); + var eventName = match[ 1 ] + instance.eventNamespace; + var selector = match[ 2 ]; + + if ( selector ) { + delegateElement.on( eventName, selector, handlerProxy ); + } else { + element.on( eventName, handlerProxy ); + } + } ); + }, + + _off: function( element, eventName ) { + eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + + this.eventNamespace; + element.off( eventName ).off( eventName ); + + // Clear the stack to avoid memory leaks (#10056) + this.bindings = $( this.bindings.not( element ).get() ); + this.focusable = $( this.focusable.not( element ).get() ); + this.hoverable = $( this.hoverable.not( element ).get() ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); + }, + mouseleave: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); + } + } ); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); + }, + focusout: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); + } + } ); + }, + + _trigger: function( type, event, data ) { + var prop, orig; + var callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + + // The original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // Copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + return !( $.isFunction( callback ) && + callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || + event.isDefaultPrevented() ); + } +}; + +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + + var hasOptions; + var effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } + + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + + if ( options.delay ) { + element.delay( options.delay ); + } + + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue( function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + } ); + } + }; +} ); + +var widget = $.widget; + + +/*! + * jQuery UI Position 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/position/ + */ + +//>>label: Position +//>>group: Core +//>>description: Positions elements relative to other elements. +//>>docs: http://api.jqueryui.com/position/ +//>>demos: http://jqueryui.com/position/ + + +( function() { +var cachedScrollbarWidth, + max = Math.max, + abs = Math.abs, + rhorizontal = /left|center|right/, + rvertical = /top|center|bottom/, + roffset = /[\+\-]\d+(\.[\d]+)?%?/, + rposition = /^\w+/, + rpercent = /%$/, + _position = $.fn.position; + +function getOffsets( offsets, width, height ) { + return [ + parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), + parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) + ]; +} + +function parseCss( element, property ) { + return parseInt( $.css( element, property ), 10 ) || 0; +} + +function getDimensions( elem ) { + var raw = elem[ 0 ]; + if ( raw.nodeType === 9 ) { + return { + width: elem.width(), + height: elem.height(), + offset: { top: 0, left: 0 } + }; + } + if ( $.isWindow( raw ) ) { + return { + width: elem.width(), + height: elem.height(), + offset: { top: elem.scrollTop(), left: elem.scrollLeft() } + }; + } + if ( raw.preventDefault ) { + return { + width: 0, + height: 0, + offset: { top: raw.pageY, left: raw.pageX } + }; + } + return { + width: elem.outerWidth(), + height: elem.outerHeight(), + offset: elem.offset() + }; +} + +$.position = { + scrollbarWidth: function() { + if ( cachedScrollbarWidth !== undefined ) { + return cachedScrollbarWidth; + } + var w1, w2, + div = $( "
" + + "
" ), + innerDiv = div.children()[ 0 ]; + + $( "body" ).append( div ); + w1 = innerDiv.offsetWidth; + div.css( "overflow", "scroll" ); + + w2 = innerDiv.offsetWidth; + + if ( w1 === w2 ) { + w2 = div[ 0 ].clientWidth; + } + + div.remove(); + + return ( cachedScrollbarWidth = w1 - w2 ); + }, + getScrollInfo: function( within ) { + var overflowX = within.isWindow || within.isDocument ? "" : + within.element.css( "overflow-x" ), + overflowY = within.isWindow || within.isDocument ? "" : + within.element.css( "overflow-y" ), + hasOverflowX = overflowX === "scroll" || + ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ), + hasOverflowY = overflowY === "scroll" || + ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight ); + return { + width: hasOverflowY ? $.position.scrollbarWidth() : 0, + height: hasOverflowX ? $.position.scrollbarWidth() : 0 + }; + }, + getWithinInfo: function( element ) { + var withinElement = $( element || window ), + isWindow = $.isWindow( withinElement[ 0 ] ), + isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9, + hasOffset = !isWindow && !isDocument; + return { + element: withinElement, + isWindow: isWindow, + isDocument: isDocument, + offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 }, + scrollLeft: withinElement.scrollLeft(), + scrollTop: withinElement.scrollTop(), + width: withinElement.outerWidth(), + height: withinElement.outerHeight() + }; + } +}; + +$.fn.position = function( options ) { + if ( !options || !options.of ) { + return _position.apply( this, arguments ); + } + + // Make a copy, we don't want to modify arguments + options = $.extend( {}, options ); + + var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, + target = $( options.of ), + within = $.position.getWithinInfo( options.within ), + scrollInfo = $.position.getScrollInfo( within ), + collision = ( options.collision || "flip" ).split( " " ), + offsets = {}; + + dimensions = getDimensions( target ); + if ( target[ 0 ].preventDefault ) { + + // Force left top to allow flipping + options.at = "left top"; + } + targetWidth = dimensions.width; + targetHeight = dimensions.height; + targetOffset = dimensions.offset; + + // Clone to reuse original targetOffset later + basePosition = $.extend( {}, targetOffset ); + + // Force my and at to have valid horizontal and vertical positions + // if a value is missing or invalid, it will be converted to center + $.each( [ "my", "at" ], function() { + var pos = ( options[ this ] || "" ).split( " " ), + horizontalOffset, + verticalOffset; + + if ( pos.length === 1 ) { + pos = rhorizontal.test( pos[ 0 ] ) ? + pos.concat( [ "center" ] ) : + rvertical.test( pos[ 0 ] ) ? + [ "center" ].concat( pos ) : + [ "center", "center" ]; + } + pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; + pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; + + // Calculate offsets + horizontalOffset = roffset.exec( pos[ 0 ] ); + verticalOffset = roffset.exec( pos[ 1 ] ); + offsets[ this ] = [ + horizontalOffset ? horizontalOffset[ 0 ] : 0, + verticalOffset ? verticalOffset[ 0 ] : 0 + ]; + + // Reduce to just the positions without the offsets + options[ this ] = [ + rposition.exec( pos[ 0 ] )[ 0 ], + rposition.exec( pos[ 1 ] )[ 0 ] + ]; + } ); + + // Normalize collision option + if ( collision.length === 1 ) { + collision[ 1 ] = collision[ 0 ]; + } + + if ( options.at[ 0 ] === "right" ) { + basePosition.left += targetWidth; + } else if ( options.at[ 0 ] === "center" ) { + basePosition.left += targetWidth / 2; + } + + if ( options.at[ 1 ] === "bottom" ) { + basePosition.top += targetHeight; + } else if ( options.at[ 1 ] === "center" ) { + basePosition.top += targetHeight / 2; + } + + atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); + basePosition.left += atOffset[ 0 ]; + basePosition.top += atOffset[ 1 ]; + + return this.each( function() { + var collisionPosition, using, + elem = $( this ), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseCss( this, "marginLeft" ), + marginTop = parseCss( this, "marginTop" ), + collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + + scrollInfo.width, + collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + + scrollInfo.height, + position = $.extend( {}, basePosition ), + myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); + + if ( options.my[ 0 ] === "right" ) { + position.left -= elemWidth; + } else if ( options.my[ 0 ] === "center" ) { + position.left -= elemWidth / 2; + } + + if ( options.my[ 1 ] === "bottom" ) { + position.top -= elemHeight; + } else if ( options.my[ 1 ] === "center" ) { + position.top -= elemHeight / 2; + } + + position.left += myOffset[ 0 ]; + position.top += myOffset[ 1 ]; + + collisionPosition = { + marginLeft: marginLeft, + marginTop: marginTop + }; + + $.each( [ "left", "top" ], function( i, dir ) { + if ( $.ui.position[ collision[ i ] ] ) { + $.ui.position[ collision[ i ] ][ dir ]( position, { + targetWidth: targetWidth, + targetHeight: targetHeight, + elemWidth: elemWidth, + elemHeight: elemHeight, + collisionPosition: collisionPosition, + collisionWidth: collisionWidth, + collisionHeight: collisionHeight, + offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], + my: options.my, + at: options.at, + within: within, + elem: elem + } ); + } + } ); + + if ( options.using ) { + + // Adds feedback as second argument to using callback, if present + using = function( props ) { + var left = targetOffset.left - position.left, + right = left + targetWidth - elemWidth, + top = targetOffset.top - position.top, + bottom = top + targetHeight - elemHeight, + feedback = { + target: { + element: target, + left: targetOffset.left, + top: targetOffset.top, + width: targetWidth, + height: targetHeight + }, + element: { + element: elem, + left: position.left, + top: position.top, + width: elemWidth, + height: elemHeight + }, + horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", + vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" + }; + if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { + feedback.horizontal = "center"; + } + if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { + feedback.vertical = "middle"; + } + if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { + feedback.important = "horizontal"; + } else { + feedback.important = "vertical"; + } + options.using.call( this, props, feedback ); + }; + } + + elem.offset( $.extend( position, { using: using } ) ); + } ); +}; + +$.ui.position = { + fit: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, + outerWidth = within.width, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = withinOffset - collisionPosLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, + newOverRight; + + // Element is wider than within + if ( data.collisionWidth > outerWidth ) { + + // Element is initially over the left side of within + if ( overLeft > 0 && overRight <= 0 ) { + newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - + withinOffset; + position.left += overLeft - newOverRight; + + // Element is initially over right side of within + } else if ( overRight > 0 && overLeft <= 0 ) { + position.left = withinOffset; + + // Element is initially over both left and right sides of within + } else { + if ( overLeft > overRight ) { + position.left = withinOffset + outerWidth - data.collisionWidth; + } else { + position.left = withinOffset; + } + } + + // Too far left -> align with left edge + } else if ( overLeft > 0 ) { + position.left += overLeft; + + // Too far right -> align with right edge + } else if ( overRight > 0 ) { + position.left -= overRight; + + // Adjust based on position and margin + } else { + position.left = max( position.left - collisionPosLeft, position.left ); + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollTop : within.offset.top, + outerHeight = data.within.height, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = withinOffset - collisionPosTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, + newOverBottom; + + // Element is taller than within + if ( data.collisionHeight > outerHeight ) { + + // Element is initially over the top of within + if ( overTop > 0 && overBottom <= 0 ) { + newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - + withinOffset; + position.top += overTop - newOverBottom; + + // Element is initially over bottom of within + } else if ( overBottom > 0 && overTop <= 0 ) { + position.top = withinOffset; + + // Element is initially over both top and bottom of within + } else { + if ( overTop > overBottom ) { + position.top = withinOffset + outerHeight - data.collisionHeight; + } else { + position.top = withinOffset; + } + } + + // Too far up -> align with top + } else if ( overTop > 0 ) { + position.top += overTop; + + // Too far down -> align with bottom edge + } else if ( overBottom > 0 ) { + position.top -= overBottom; + + // Adjust based on position and margin + } else { + position.top = max( position.top - collisionPosTop, position.top ); + } + } + }, + flip: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.offset.left + within.scrollLeft, + outerWidth = within.width, + offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = collisionPosLeft - offsetLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + data.at[ 0 ] === "right" ? + -data.targetWidth : + 0, + offset = -2 * data.offset[ 0 ], + newOverRight, + newOverLeft; + + if ( overLeft < 0 ) { + newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - + outerWidth - withinOffset; + if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { + position.left += myOffset + atOffset + offset; + } + } else if ( overRight > 0 ) { + newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + + atOffset + offset - offsetLeft; + if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { + position.left += myOffset + atOffset + offset; + } + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.offset.top + within.scrollTop, + outerHeight = within.height, + offsetTop = within.isWindow ? within.scrollTop : within.offset.top, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = collisionPosTop - offsetTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, + top = data.my[ 1 ] === "top", + myOffset = top ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + data.at[ 1 ] === "bottom" ? + -data.targetHeight : + 0, + offset = -2 * data.offset[ 1 ], + newOverTop, + newOverBottom; + if ( overTop < 0 ) { + newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - + outerHeight - withinOffset; + if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { + position.top += myOffset + atOffset + offset; + } + } else if ( overBottom > 0 ) { + newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + + offset - offsetTop; + if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { + position.top += myOffset + atOffset + offset; + } + } + } + }, + flipfit: { + left: function() { + $.ui.position.flip.left.apply( this, arguments ); + $.ui.position.fit.left.apply( this, arguments ); + }, + top: function() { + $.ui.position.flip.top.apply( this, arguments ); + $.ui.position.fit.top.apply( this, arguments ); + } + } +}; + +} )(); + +var position = $.ui.position; + + +/*! + * jQuery UI :data 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: :data Selector +//>>group: Core +//>>description: Selects elements which have data stored under the specified key. +//>>docs: http://api.jqueryui.com/data-selector/ + + +var data = $.extend( $.expr[ ":" ], { + data: $.expr.createPseudo ? + $.expr.createPseudo( function( dataName ) { + return function( elem ) { + return !!$.data( elem, dataName ); + }; + } ) : + + // Support: jQuery <1.8 + function( elem, i, match ) { + return !!$.data( elem, match[ 3 ] ); + } +} ); + +/*! + * jQuery UI Disable Selection 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: disableSelection +//>>group: Core +//>>description: Disable selection of text content within the set of matched elements. +//>>docs: http://api.jqueryui.com/disableSelection/ + +// This file is deprecated + + +var disableSelection = $.fn.extend( { + disableSelection: ( function() { + var eventType = "onselectstart" in document.createElement( "div" ) ? + "selectstart" : + "mousedown"; + + return function() { + return this.on( eventType + ".ui-disableSelection", function( event ) { + event.preventDefault(); + } ); + }; + } )(), + + enableSelection: function() { + return this.off( ".ui-disableSelection" ); + } +} ); + + +/*! + * jQuery UI Effects 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Effects Core +//>>group: Effects +// jscs:disable maximumLineLength +//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects. +// jscs:enable maximumLineLength +//>>docs: http://api.jqueryui.com/category/effects-core/ +//>>demos: http://jqueryui.com/effect/ + + + +var dataSpace = "ui-effects-", + dataSpaceStyle = "ui-effects-style", + dataSpaceAnimated = "ui-effects-animated", + + // Create a local jQuery because jQuery Color relies on it and the + // global may not exist with AMD and a custom build (#10199) + jQuery = $; + +$.effects = { + effect: {} +}; + +/*! + * jQuery Color Animations v2.1.2 + * https://github.com/jquery/jquery-color + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * Date: Wed Jan 16 08:47:09 2013 -0600 + */ +( function( jQuery, undefined ) { + + var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + + "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", + + // Plusequals test for += 100 -= 100 + rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, + + // A set of RE's that can match strings and generate color tuples. + stringParsers = [ { + re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ], + execResult[ 3 ], + execResult[ 4 ] + ]; + } + }, { + re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ] * 2.55, + execResult[ 2 ] * 2.55, + execResult[ 3 ] * 2.55, + execResult[ 4 ] + ]; + } + }, { + + // This regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ], 16 ) + ]; + } + }, { + + // This regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) + ]; + } + }, { + re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + space: "hsla", + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ] / 100, + execResult[ 3 ] / 100, + execResult[ 4 ] + ]; + } + } ], + + // JQuery.Color( ) + color = jQuery.Color = function( color, green, blue, alpha ) { + return new jQuery.Color.fn.parse( color, green, blue, alpha ); + }, + spaces = { + rgba: { + props: { + red: { + idx: 0, + type: "byte" + }, + green: { + idx: 1, + type: "byte" + }, + blue: { + idx: 2, + type: "byte" + } + } + }, + + hsla: { + props: { + hue: { + idx: 0, + type: "degrees" + }, + saturation: { + idx: 1, + type: "percent" + }, + lightness: { + idx: 2, + type: "percent" + } + } + } + }, + propTypes = { + "byte": { + floor: true, + max: 255 + }, + "percent": { + max: 1 + }, + "degrees": { + mod: 360, + floor: true + } + }, + support = color.support = {}, + + // Element for support tests + supportElem = jQuery( "

" )[ 0 ], + + // Colors = jQuery.Color.names + colors, + + // Local aliases of functions called often + each = jQuery.each; + +// Determine rgba support immediately +supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; +support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; + +// Define cache name and alpha properties +// for rgba and hsla spaces +each( spaces, function( spaceName, space ) { + space.cache = "_" + spaceName; + space.props.alpha = { + idx: 3, + type: "percent", + def: 1 + }; +} ); + +function clamp( value, prop, allowEmpty ) { + var type = propTypes[ prop.type ] || {}; + + if ( value == null ) { + return ( allowEmpty || !prop.def ) ? null : prop.def; + } + + // ~~ is an short way of doing floor for positive numbers + value = type.floor ? ~~value : parseFloat( value ); + + // IE will pass in empty strings as value for alpha, + // which will hit this case + if ( isNaN( value ) ) { + return prop.def; + } + + if ( type.mod ) { + + // We add mod before modding to make sure that negatives values + // get converted properly: -10 -> 350 + return ( value + type.mod ) % type.mod; + } + + // For now all property types without mod have min and max + return 0 > value ? 0 : type.max < value ? type.max : value; +} + +function stringParse( string ) { + var inst = color(), + rgba = inst._rgba = []; + + string = string.toLowerCase(); + + each( stringParsers, function( i, parser ) { + var parsed, + match = parser.re.exec( string ), + values = match && parser.parse( match ), + spaceName = parser.space || "rgba"; + + if ( values ) { + parsed = inst[ spaceName ]( values ); + + // If this was an rgba parse the assignment might happen twice + // oh well.... + inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; + rgba = inst._rgba = parsed._rgba; + + // Exit each( stringParsers ) here because we matched + return false; + } + } ); + + // Found a stringParser that handled it + if ( rgba.length ) { + + // If this came from a parsed string, force "transparent" when alpha is 0 + // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) + if ( rgba.join() === "0,0,0,0" ) { + jQuery.extend( rgba, colors.transparent ); + } + return inst; + } + + // Named colors + return colors[ string ]; +} + +color.fn = jQuery.extend( color.prototype, { + parse: function( red, green, blue, alpha ) { + if ( red === undefined ) { + this._rgba = [ null, null, null, null ]; + return this; + } + if ( red.jquery || red.nodeType ) { + red = jQuery( red ).css( green ); + green = undefined; + } + + var inst = this, + type = jQuery.type( red ), + rgba = this._rgba = []; + + // More than 1 argument specified - assume ( red, green, blue, alpha ) + if ( green !== undefined ) { + red = [ red, green, blue, alpha ]; + type = "array"; + } + + if ( type === "string" ) { + return this.parse( stringParse( red ) || colors._default ); + } + + if ( type === "array" ) { + each( spaces.rgba.props, function( key, prop ) { + rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); + } ); + return this; + } + + if ( type === "object" ) { + if ( red instanceof color ) { + each( spaces, function( spaceName, space ) { + if ( red[ space.cache ] ) { + inst[ space.cache ] = red[ space.cache ].slice(); + } + } ); + } else { + each( spaces, function( spaceName, space ) { + var cache = space.cache; + each( space.props, function( key, prop ) { + + // If the cache doesn't exist, and we know how to convert + if ( !inst[ cache ] && space.to ) { + + // If the value was null, we don't need to copy it + // if the key was alpha, we don't need to copy it either + if ( key === "alpha" || red[ key ] == null ) { + return; + } + inst[ cache ] = space.to( inst._rgba ); + } + + // This is the only case where we allow nulls for ALL properties. + // call clamp with alwaysAllowEmpty + inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); + } ); + + // Everything defined but alpha? + if ( inst[ cache ] && + jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { + + // Use the default of 1 + inst[ cache ][ 3 ] = 1; + if ( space.from ) { + inst._rgba = space.from( inst[ cache ] ); + } + } + } ); + } + return this; + } + }, + is: function( compare ) { + var is = color( compare ), + same = true, + inst = this; + + each( spaces, function( _, space ) { + var localCache, + isCache = is[ space.cache ]; + if ( isCache ) { + localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; + each( space.props, function( _, prop ) { + if ( isCache[ prop.idx ] != null ) { + same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); + return same; + } + } ); + } + return same; + } ); + return same; + }, + _space: function() { + var used = [], + inst = this; + each( spaces, function( spaceName, space ) { + if ( inst[ space.cache ] ) { + used.push( spaceName ); + } + } ); + return used.pop(); + }, + transition: function( other, distance ) { + var end = color( other ), + spaceName = end._space(), + space = spaces[ spaceName ], + startColor = this.alpha() === 0 ? color( "transparent" ) : this, + start = startColor[ space.cache ] || space.to( startColor._rgba ), + result = start.slice(); + + end = end[ space.cache ]; + each( space.props, function( key, prop ) { + var index = prop.idx, + startValue = start[ index ], + endValue = end[ index ], + type = propTypes[ prop.type ] || {}; + + // If null, don't override start value + if ( endValue === null ) { + return; + } + + // If null - use end + if ( startValue === null ) { + result[ index ] = endValue; + } else { + if ( type.mod ) { + if ( endValue - startValue > type.mod / 2 ) { + startValue += type.mod; + } else if ( startValue - endValue > type.mod / 2 ) { + startValue -= type.mod; + } + } + result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); + } + } ); + return this[ spaceName ]( result ); + }, + blend: function( opaque ) { + + // If we are already opaque - return ourself + if ( this._rgba[ 3 ] === 1 ) { + return this; + } + + var rgb = this._rgba.slice(), + a = rgb.pop(), + blend = color( opaque )._rgba; + + return color( jQuery.map( rgb, function( v, i ) { + return ( 1 - a ) * blend[ i ] + a * v; + } ) ); + }, + toRgbaString: function() { + var prefix = "rgba(", + rgba = jQuery.map( this._rgba, function( v, i ) { + return v == null ? ( i > 2 ? 1 : 0 ) : v; + } ); + + if ( rgba[ 3 ] === 1 ) { + rgba.pop(); + prefix = "rgb("; + } + + return prefix + rgba.join() + ")"; + }, + toHslaString: function() { + var prefix = "hsla(", + hsla = jQuery.map( this.hsla(), function( v, i ) { + if ( v == null ) { + v = i > 2 ? 1 : 0; + } + + // Catch 1 and 2 + if ( i && i < 3 ) { + v = Math.round( v * 100 ) + "%"; + } + return v; + } ); + + if ( hsla[ 3 ] === 1 ) { + hsla.pop(); + prefix = "hsl("; + } + return prefix + hsla.join() + ")"; + }, + toHexString: function( includeAlpha ) { + var rgba = this._rgba.slice(), + alpha = rgba.pop(); + + if ( includeAlpha ) { + rgba.push( ~~( alpha * 255 ) ); + } + + return "#" + jQuery.map( rgba, function( v ) { + + // Default to 0 when nulls exist + v = ( v || 0 ).toString( 16 ); + return v.length === 1 ? "0" + v : v; + } ).join( "" ); + }, + toString: function() { + return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); + } +} ); +color.fn.parse.prototype = color.fn; + +// Hsla conversions adapted from: +// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 + +function hue2rgb( p, q, h ) { + h = ( h + 1 ) % 1; + if ( h * 6 < 1 ) { + return p + ( q - p ) * h * 6; + } + if ( h * 2 < 1 ) { + return q; + } + if ( h * 3 < 2 ) { + return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; + } + return p; +} + +spaces.hsla.to = function( rgba ) { + if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { + return [ null, null, null, rgba[ 3 ] ]; + } + var r = rgba[ 0 ] / 255, + g = rgba[ 1 ] / 255, + b = rgba[ 2 ] / 255, + a = rgba[ 3 ], + max = Math.max( r, g, b ), + min = Math.min( r, g, b ), + diff = max - min, + add = max + min, + l = add * 0.5, + h, s; + + if ( min === max ) { + h = 0; + } else if ( r === max ) { + h = ( 60 * ( g - b ) / diff ) + 360; + } else if ( g === max ) { + h = ( 60 * ( b - r ) / diff ) + 120; + } else { + h = ( 60 * ( r - g ) / diff ) + 240; + } + + // Chroma (diff) == 0 means greyscale which, by definition, saturation = 0% + // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) + if ( diff === 0 ) { + s = 0; + } else if ( l <= 0.5 ) { + s = diff / add; + } else { + s = diff / ( 2 - add ); + } + return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ]; +}; + +spaces.hsla.from = function( hsla ) { + if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { + return [ null, null, null, hsla[ 3 ] ]; + } + var h = hsla[ 0 ] / 360, + s = hsla[ 1 ], + l = hsla[ 2 ], + a = hsla[ 3 ], + q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, + p = 2 * l - q; + + return [ + Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), + Math.round( hue2rgb( p, q, h ) * 255 ), + Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), + a + ]; +}; + +each( spaces, function( spaceName, space ) { + var props = space.props, + cache = space.cache, + to = space.to, + from = space.from; + + // Makes rgba() and hsla() + color.fn[ spaceName ] = function( value ) { + + // Generate a cache for this space if it doesn't exist + if ( to && !this[ cache ] ) { + this[ cache ] = to( this._rgba ); + } + if ( value === undefined ) { + return this[ cache ].slice(); + } + + var ret, + type = jQuery.type( value ), + arr = ( type === "array" || type === "object" ) ? value : arguments, + local = this[ cache ].slice(); + + each( props, function( key, prop ) { + var val = arr[ type === "object" ? key : prop.idx ]; + if ( val == null ) { + val = local[ prop.idx ]; + } + local[ prop.idx ] = clamp( val, prop ); + } ); + + if ( from ) { + ret = color( from( local ) ); + ret[ cache ] = local; + return ret; + } else { + return color( local ); + } + }; + + // Makes red() green() blue() alpha() hue() saturation() lightness() + each( props, function( key, prop ) { + + // Alpha is included in more than one space + if ( color.fn[ key ] ) { + return; + } + color.fn[ key ] = function( value ) { + var vtype = jQuery.type( value ), + fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), + local = this[ fn ](), + cur = local[ prop.idx ], + match; + + if ( vtype === "undefined" ) { + return cur; + } + + if ( vtype === "function" ) { + value = value.call( this, cur ); + vtype = jQuery.type( value ); + } + if ( value == null && prop.empty ) { + return this; + } + if ( vtype === "string" ) { + match = rplusequals.exec( value ); + if ( match ) { + value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); + } + } + local[ prop.idx ] = value; + return this[ fn ]( local ); + }; + } ); +} ); + +// Add cssHook and .fx.step function for each named hook. +// accept a space separated string of properties +color.hook = function( hook ) { + var hooks = hook.split( " " ); + each( hooks, function( i, hook ) { + jQuery.cssHooks[ hook ] = { + set: function( elem, value ) { + var parsed, curElem, + backgroundColor = ""; + + if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || + ( parsed = stringParse( value ) ) ) ) { + value = color( parsed || value ); + if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { + curElem = hook === "backgroundColor" ? elem.parentNode : elem; + while ( + ( backgroundColor === "" || backgroundColor === "transparent" ) && + curElem && curElem.style + ) { + try { + backgroundColor = jQuery.css( curElem, "backgroundColor" ); + curElem = curElem.parentNode; + } catch ( e ) { + } + } + + value = value.blend( backgroundColor && backgroundColor !== "transparent" ? + backgroundColor : + "_default" ); + } + + value = value.toRgbaString(); + } + try { + elem.style[ hook ] = value; + } catch ( e ) { + + // Wrapped to prevent IE from throwing errors on "invalid" values like + // 'auto' or 'inherit' + } + } + }; + jQuery.fx.step[ hook ] = function( fx ) { + if ( !fx.colorInit ) { + fx.start = color( fx.elem, hook ); + fx.end = color( fx.end ); + fx.colorInit = true; + } + jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); + }; + } ); + +}; + +color.hook( stepHooks ); + +jQuery.cssHooks.borderColor = { + expand: function( value ) { + var expanded = {}; + + each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { + expanded[ "border" + part + "Color" ] = value; + } ); + return expanded; + } +}; + +// Basic color names only. +// Usage of any of the other color names requires adding yourself or including +// jquery.color.svg-names.js. +colors = jQuery.Color.names = { + + // 4.1. Basic color keywords + aqua: "#00ffff", + black: "#000000", + blue: "#0000ff", + fuchsia: "#ff00ff", + gray: "#808080", + green: "#008000", + lime: "#00ff00", + maroon: "#800000", + navy: "#000080", + olive: "#808000", + purple: "#800080", + red: "#ff0000", + silver: "#c0c0c0", + teal: "#008080", + white: "#ffffff", + yellow: "#ffff00", + + // 4.2.3. "transparent" color keyword + transparent: [ null, null, null, 0 ], + + _default: "#ffffff" +}; + +} )( jQuery ); + +/******************************************************************************/ +/****************************** CLASS ANIMATIONS ******************************/ +/******************************************************************************/ +( function() { + +var classAnimationActions = [ "add", "remove", "toggle" ], + shorthandStyles = { + border: 1, + borderBottom: 1, + borderColor: 1, + borderLeft: 1, + borderRight: 1, + borderTop: 1, + borderWidth: 1, + margin: 1, + padding: 1 + }; + +$.each( + [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], + function( _, prop ) { + $.fx.step[ prop ] = function( fx ) { + if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { + jQuery.style( fx.elem, prop, fx.end ); + fx.setAttr = true; + } + }; + } +); + +function getElementStyles( elem ) { + var key, len, + style = elem.ownerDocument.defaultView ? + elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : + elem.currentStyle, + styles = {}; + + if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { + len = style.length; + while ( len-- ) { + key = style[ len ]; + if ( typeof style[ key ] === "string" ) { + styles[ $.camelCase( key ) ] = style[ key ]; + } + } + + // Support: Opera, IE <9 + } else { + for ( key in style ) { + if ( typeof style[ key ] === "string" ) { + styles[ key ] = style[ key ]; + } + } + } + + return styles; +} + +function styleDifference( oldStyle, newStyle ) { + var diff = {}, + name, value; + + for ( name in newStyle ) { + value = newStyle[ name ]; + if ( oldStyle[ name ] !== value ) { + if ( !shorthandStyles[ name ] ) { + if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { + diff[ name ] = value; + } + } + } + } + + return diff; +} + +// Support: jQuery <1.8 +if ( !$.fn.addBack ) { + $.fn.addBack = function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + }; +} + +$.effects.animateClass = function( value, duration, easing, callback ) { + var o = $.speed( duration, easing, callback ); + + return this.queue( function() { + var animated = $( this ), + baseClass = animated.attr( "class" ) || "", + applyClassChange, + allAnimations = o.children ? animated.find( "*" ).addBack() : animated; + + // Map the animated objects to store the original styles. + allAnimations = allAnimations.map( function() { + var el = $( this ); + return { + el: el, + start: getElementStyles( this ) + }; + } ); + + // Apply class change + applyClassChange = function() { + $.each( classAnimationActions, function( i, action ) { + if ( value[ action ] ) { + animated[ action + "Class" ]( value[ action ] ); + } + } ); + }; + applyClassChange(); + + // Map all animated objects again - calculate new styles and diff + allAnimations = allAnimations.map( function() { + this.end = getElementStyles( this.el[ 0 ] ); + this.diff = styleDifference( this.start, this.end ); + return this; + } ); + + // Apply original class + animated.attr( "class", baseClass ); + + // Map all animated objects again - this time collecting a promise + allAnimations = allAnimations.map( function() { + var styleInfo = this, + dfd = $.Deferred(), + opts = $.extend( {}, o, { + queue: false, + complete: function() { + dfd.resolve( styleInfo ); + } + } ); + + this.el.animate( this.diff, opts ); + return dfd.promise(); + } ); + + // Once all animations have completed: + $.when.apply( $, allAnimations.get() ).done( function() { + + // Set the final class + applyClassChange(); + + // For each animated element, + // clear all css properties that were animated + $.each( arguments, function() { + var el = this.el; + $.each( this.diff, function( key ) { + el.css( key, "" ); + } ); + } ); + + // This is guarnteed to be there if you use jQuery.speed() + // it also handles dequeuing the next anim... + o.complete.call( animated[ 0 ] ); + } ); + } ); +}; + +$.fn.extend( { + addClass: ( function( orig ) { + return function( classNames, speed, easing, callback ) { + return speed ? + $.effects.animateClass.call( this, + { add: classNames }, speed, easing, callback ) : + orig.apply( this, arguments ); + }; + } )( $.fn.addClass ), + + removeClass: ( function( orig ) { + return function( classNames, speed, easing, callback ) { + return arguments.length > 1 ? + $.effects.animateClass.call( this, + { remove: classNames }, speed, easing, callback ) : + orig.apply( this, arguments ); + }; + } )( $.fn.removeClass ), + + toggleClass: ( function( orig ) { + return function( classNames, force, speed, easing, callback ) { + if ( typeof force === "boolean" || force === undefined ) { + if ( !speed ) { + + // Without speed parameter + return orig.apply( this, arguments ); + } else { + return $.effects.animateClass.call( this, + ( force ? { add: classNames } : { remove: classNames } ), + speed, easing, callback ); + } + } else { + + // Without force parameter + return $.effects.animateClass.call( this, + { toggle: classNames }, force, speed, easing ); + } + }; + } )( $.fn.toggleClass ), + + switchClass: function( remove, add, speed, easing, callback ) { + return $.effects.animateClass.call( this, { + add: add, + remove: remove + }, speed, easing, callback ); + } +} ); + +} )(); + +/******************************************************************************/ +/*********************************** EFFECTS **********************************/ +/******************************************************************************/ + +( function() { + +if ( $.expr && $.expr.filters && $.expr.filters.animated ) { + $.expr.filters.animated = ( function( orig ) { + return function( elem ) { + return !!$( elem ).data( dataSpaceAnimated ) || orig( elem ); + }; + } )( $.expr.filters.animated ); +} + +if ( $.uiBackCompat !== false ) { + $.extend( $.effects, { + + // Saves a set of properties in a data storage + save: function( element, set ) { + var i = 0, length = set.length; + for ( ; i < length; i++ ) { + if ( set[ i ] !== null ) { + element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); + } + } + }, + + // Restores a set of previously saved properties from a data storage + restore: function( element, set ) { + var val, i = 0, length = set.length; + for ( ; i < length; i++ ) { + if ( set[ i ] !== null ) { + val = element.data( dataSpace + set[ i ] ); + element.css( set[ i ], val ); + } + } + }, + + setMode: function( el, mode ) { + if ( mode === "toggle" ) { + mode = el.is( ":hidden" ) ? "show" : "hide"; + } + return mode; + }, + + // Wraps the element around a wrapper that copies position properties + createWrapper: function( element ) { + + // If the element is already wrapped, return it + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + return element.parent(); + } + + // Wrap the element + var props = { + width: element.outerWidth( true ), + height: element.outerHeight( true ), + "float": element.css( "float" ) + }, + wrapper = $( "

" ) + .addClass( "ui-effects-wrapper" ) + .css( { + fontSize: "100%", + background: "transparent", + border: "none", + margin: 0, + padding: 0 + } ), + + // Store the size in case width/height are defined in % - Fixes #5245 + size = { + width: element.width(), + height: element.height() + }, + active = document.activeElement; + + // Support: Firefox + // Firefox incorrectly exposes anonymous content + // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 + try { + active.id; + } catch ( e ) { + active = document.body; + } + + element.wrap( wrapper ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).trigger( "focus" ); + } + + // Hotfix for jQuery 1.4 since some change in wrap() seems to actually + // lose the reference to the wrapped element + wrapper = element.parent(); + + // Transfer positioning properties to the wrapper + if ( element.css( "position" ) === "static" ) { + wrapper.css( { position: "relative" } ); + element.css( { position: "relative" } ); + } else { + $.extend( props, { + position: element.css( "position" ), + zIndex: element.css( "z-index" ) + } ); + $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) { + props[ pos ] = element.css( pos ); + if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { + props[ pos ] = "auto"; + } + } ); + element.css( { + position: "relative", + top: 0, + left: 0, + right: "auto", + bottom: "auto" + } ); + } + element.css( size ); + + return wrapper.css( props ).show(); + }, + + removeWrapper: function( element ) { + var active = document.activeElement; + + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + element.parent().replaceWith( element ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).trigger( "focus" ); + } + } + + return element; + } + } ); +} + +$.extend( $.effects, { + version: "1.12.1", + + define: function( name, mode, effect ) { + if ( !effect ) { + effect = mode; + mode = "effect"; + } + + $.effects.effect[ name ] = effect; + $.effects.effect[ name ].mode = mode; + + return effect; + }, + + scaledDimensions: function( element, percent, direction ) { + if ( percent === 0 ) { + return { + height: 0, + width: 0, + outerHeight: 0, + outerWidth: 0 + }; + } + + var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1, + y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1; + + return { + height: element.height() * y, + width: element.width() * x, + outerHeight: element.outerHeight() * y, + outerWidth: element.outerWidth() * x + }; + + }, + + clipToBox: function( animation ) { + return { + width: animation.clip.right - animation.clip.left, + height: animation.clip.bottom - animation.clip.top, + left: animation.clip.left, + top: animation.clip.top + }; + }, + + // Injects recently queued functions to be first in line (after "inprogress") + unshift: function( element, queueLength, count ) { + var queue = element.queue(); + + if ( queueLength > 1 ) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queueLength, count ) ) ); + } + element.dequeue(); + }, + + saveStyle: function( element ) { + element.data( dataSpaceStyle, element[ 0 ].style.cssText ); + }, + + restoreStyle: function( element ) { + element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || ""; + element.removeData( dataSpaceStyle ); + }, + + mode: function( element, mode ) { + var hidden = element.is( ":hidden" ); + + if ( mode === "toggle" ) { + mode = hidden ? "show" : "hide"; + } + if ( hidden ? mode === "hide" : mode === "show" ) { + mode = "none"; + } + return mode; + }, + + // Translates a [top,left] array into a baseline value + getBaseline: function( origin, original ) { + var y, x; + + switch ( origin[ 0 ] ) { + case "top": + y = 0; + break; + case "middle": + y = 0.5; + break; + case "bottom": + y = 1; + break; + default: + y = origin[ 0 ] / original.height; + } + + switch ( origin[ 1 ] ) { + case "left": + x = 0; + break; + case "center": + x = 0.5; + break; + case "right": + x = 1; + break; + default: + x = origin[ 1 ] / original.width; + } + + return { + x: x, + y: y + }; + }, + + // Creates a placeholder element so that the original element can be made absolute + createPlaceholder: function( element ) { + var placeholder, + cssPosition = element.css( "position" ), + position = element.position(); + + // Lock in margins first to account for form elements, which + // will change margin if you explicitly set height + // see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380 + // Support: Safari + element.css( { + marginTop: element.css( "marginTop" ), + marginBottom: element.css( "marginBottom" ), + marginLeft: element.css( "marginLeft" ), + marginRight: element.css( "marginRight" ) + } ) + .outerWidth( element.outerWidth() ) + .outerHeight( element.outerHeight() ); + + if ( /^(static|relative)/.test( cssPosition ) ) { + cssPosition = "absolute"; + + placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( { + + // Convert inline to inline block to account for inline elements + // that turn to inline block based on content (like img) + display: /^(inline|ruby)/.test( element.css( "display" ) ) ? + "inline-block" : + "block", + visibility: "hidden", + + // Margins need to be set to account for margin collapse + marginTop: element.css( "marginTop" ), + marginBottom: element.css( "marginBottom" ), + marginLeft: element.css( "marginLeft" ), + marginRight: element.css( "marginRight" ), + "float": element.css( "float" ) + } ) + .outerWidth( element.outerWidth() ) + .outerHeight( element.outerHeight() ) + .addClass( "ui-effects-placeholder" ); + + element.data( dataSpace + "placeholder", placeholder ); + } + + element.css( { + position: cssPosition, + left: position.left, + top: position.top + } ); + + return placeholder; + }, + + removePlaceholder: function( element ) { + var dataKey = dataSpace + "placeholder", + placeholder = element.data( dataKey ); + + if ( placeholder ) { + placeholder.remove(); + element.removeData( dataKey ); + } + }, + + // Removes a placeholder if it exists and restores + // properties that were modified during placeholder creation + cleanUp: function( element ) { + $.effects.restoreStyle( element ); + $.effects.removePlaceholder( element ); + }, + + setTransition: function( element, list, factor, value ) { + value = value || {}; + $.each( list, function( i, x ) { + var unit = element.cssUnit( x ); + if ( unit[ 0 ] > 0 ) { + value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; + } + } ); + return value; + } +} ); + +// Return an effect options object for the given parameters: +function _normalizeArguments( effect, options, speed, callback ) { + + // Allow passing all options as the first parameter + if ( $.isPlainObject( effect ) ) { + options = effect; + effect = effect.effect; + } + + // Convert to an object + effect = { effect: effect }; + + // Catch (effect, null, ...) + if ( options == null ) { + options = {}; + } + + // Catch (effect, callback) + if ( $.isFunction( options ) ) { + callback = options; + speed = null; + options = {}; + } + + // Catch (effect, speed, ?) + if ( typeof options === "number" || $.fx.speeds[ options ] ) { + callback = speed; + speed = options; + options = {}; + } + + // Catch (effect, options, callback) + if ( $.isFunction( speed ) ) { + callback = speed; + speed = null; + } + + // Add options to effect + if ( options ) { + $.extend( effect, options ); + } + + speed = speed || options.duration; + effect.duration = $.fx.off ? 0 : + typeof speed === "number" ? speed : + speed in $.fx.speeds ? $.fx.speeds[ speed ] : + $.fx.speeds._default; + + effect.complete = callback || options.complete; + + return effect; +} + +function standardAnimationOption( option ) { + + // Valid standard speeds (nothing, number, named speed) + if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { + return true; + } + + // Invalid strings - treat as "normal" speed + if ( typeof option === "string" && !$.effects.effect[ option ] ) { + return true; + } + + // Complete callback + if ( $.isFunction( option ) ) { + return true; + } + + // Options hash (but not naming an effect) + if ( typeof option === "object" && !option.effect ) { + return true; + } + + // Didn't match any standard API + return false; +} + +$.fn.extend( { + effect: function( /* effect, options, speed, callback */ ) { + var args = _normalizeArguments.apply( this, arguments ), + effectMethod = $.effects.effect[ args.effect ], + defaultMode = effectMethod.mode, + queue = args.queue, + queueName = queue || "fx", + complete = args.complete, + mode = args.mode, + modes = [], + prefilter = function( next ) { + var el = $( this ), + normalizedMode = $.effects.mode( el, mode ) || defaultMode; + + // Sentinel for duck-punching the :animated psuedo-selector + el.data( dataSpaceAnimated, true ); + + // Save effect mode for later use, + // we can't just call $.effects.mode again later, + // as the .show() below destroys the initial state + modes.push( normalizedMode ); + + // See $.uiBackCompat inside of run() for removal of defaultMode in 1.13 + if ( defaultMode && ( normalizedMode === "show" || + ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) { + el.show(); + } + + if ( !defaultMode || normalizedMode !== "none" ) { + $.effects.saveStyle( el ); + } + + if ( $.isFunction( next ) ) { + next(); + } + }; + + if ( $.fx.off || !effectMethod ) { + + // Delegate to the original method (e.g., .show()) if possible + if ( mode ) { + return this[ mode ]( args.duration, complete ); + } else { + return this.each( function() { + if ( complete ) { + complete.call( this ); + } + } ); + } + } + + function run( next ) { + var elem = $( this ); + + function cleanup() { + elem.removeData( dataSpaceAnimated ); + + $.effects.cleanUp( elem ); + + if ( args.mode === "hide" ) { + elem.hide(); + } + + done(); + } + + function done() { + if ( $.isFunction( complete ) ) { + complete.call( elem[ 0 ] ); + } + + if ( $.isFunction( next ) ) { + next(); + } + } + + // Override mode option on a per element basis, + // as toggle can be either show or hide depending on element state + args.mode = modes.shift(); + + if ( $.uiBackCompat !== false && !defaultMode ) { + if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { + + // Call the core method to track "olddisplay" properly + elem[ mode ](); + done(); + } else { + effectMethod.call( elem[ 0 ], args, done ); + } + } else { + if ( args.mode === "none" ) { + + // Call the core method to track "olddisplay" properly + elem[ mode ](); + done(); + } else { + effectMethod.call( elem[ 0 ], args, cleanup ); + } + } + } + + // Run prefilter on all elements first to ensure that + // any showing or hiding happens before placeholder creation, + // which ensures that any layout changes are correctly captured. + return queue === false ? + this.each( prefilter ).each( run ) : + this.queue( queueName, prefilter ).queue( queueName, run ); + }, + + show: ( function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "show"; + return this.effect.call( this, args ); + } + }; + } )( $.fn.show ), + + hide: ( function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "hide"; + return this.effect.call( this, args ); + } + }; + } )( $.fn.hide ), + + toggle: ( function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) || typeof option === "boolean" ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "toggle"; + return this.effect.call( this, args ); + } + }; + } )( $.fn.toggle ), + + cssUnit: function( key ) { + var style = this.css( key ), + val = []; + + $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { + if ( style.indexOf( unit ) > 0 ) { + val = [ parseFloat( style ), unit ]; + } + } ); + return val; + }, + + cssClip: function( clipObj ) { + if ( clipObj ) { + return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + + clipObj.bottom + "px " + clipObj.left + "px)" ); + } + return parseClip( this.css( "clip" ), this ); + }, + + transfer: function( options, done ) { + var element = $( this ), + target = $( options.to ), + targetFixed = target.css( "position" ) === "fixed", + body = $( "body" ), + fixTop = targetFixed ? body.scrollTop() : 0, + fixLeft = targetFixed ? body.scrollLeft() : 0, + endPosition = target.offset(), + animation = { + top: endPosition.top - fixTop, + left: endPosition.left - fixLeft, + height: target.innerHeight(), + width: target.innerWidth() + }, + startPosition = element.offset(), + transfer = $( "
" ) + .appendTo( "body" ) + .addClass( options.className ) + .css( { + top: startPosition.top - fixTop, + left: startPosition.left - fixLeft, + height: element.innerHeight(), + width: element.innerWidth(), + position: targetFixed ? "fixed" : "absolute" + } ) + .animate( animation, options.duration, options.easing, function() { + transfer.remove(); + if ( $.isFunction( done ) ) { + done(); + } + } ); + } +} ); + +function parseClip( str, element ) { + var outerWidth = element.outerWidth(), + outerHeight = element.outerHeight(), + clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/, + values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ]; + + return { + top: parseFloat( values[ 1 ] ) || 0, + right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ), + bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ), + left: parseFloat( values[ 4 ] ) || 0 + }; +} + +$.fx.step.clip = function( fx ) { + if ( !fx.clipInit ) { + fx.start = $( fx.elem ).cssClip(); + if ( typeof fx.end === "string" ) { + fx.end = parseClip( fx.end, fx.elem ); + } + fx.clipInit = true; + } + + $( fx.elem ).cssClip( { + top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top, + right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right, + bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom, + left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left + } ); +}; + +} )(); + +/******************************************************************************/ +/*********************************** EASING ***********************************/ +/******************************************************************************/ + +( function() { + +// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing) + +var baseEasings = {}; + +$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { + baseEasings[ name ] = function( p ) { + return Math.pow( p, i + 2 ); + }; +} ); + +$.extend( baseEasings, { + Sine: function( p ) { + return 1 - Math.cos( p * Math.PI / 2 ); + }, + Circ: function( p ) { + return 1 - Math.sqrt( 1 - p * p ); + }, + Elastic: function( p ) { + return p === 0 || p === 1 ? p : + -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 ); + }, + Back: function( p ) { + return p * p * ( 3 * p - 2 ); + }, + Bounce: function( p ) { + var pow2, + bounce = 4; + + while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} + return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); + } +} ); + +$.each( baseEasings, function( name, easeIn ) { + $.easing[ "easeIn" + name ] = easeIn; + $.easing[ "easeOut" + name ] = function( p ) { + return 1 - easeIn( 1 - p ); + }; + $.easing[ "easeInOut" + name ] = function( p ) { + return p < 0.5 ? + easeIn( p * 2 ) / 2 : + 1 - easeIn( p * -2 + 2 ) / 2; + }; +} ); + +} )(); + +var effect = $.effects; + + +/*! + * jQuery UI Effects Blind 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Blind Effect +//>>group: Effects +//>>description: Blinds the element. +//>>docs: http://api.jqueryui.com/blind-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) { + var map = { + up: [ "bottom", "top" ], + vertical: [ "bottom", "top" ], + down: [ "top", "bottom" ], + left: [ "right", "left" ], + horizontal: [ "right", "left" ], + right: [ "left", "right" ] + }, + element = $( this ), + direction = options.direction || "up", + start = element.cssClip(), + animate = { clip: $.extend( {}, start ) }, + placeholder = $.effects.createPlaceholder( element ); + + animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ]; + + if ( options.mode === "show" ) { + element.cssClip( animate.clip ); + if ( placeholder ) { + placeholder.css( $.effects.clipToBox( animate ) ); + } + + animate.clip = start; + } + + if ( placeholder ) { + placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing ); + } + + element.animate( animate, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Bounce 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Bounce Effect +//>>group: Effects +//>>description: Bounces an element horizontally or vertically n times. +//>>docs: http://api.jqueryui.com/bounce-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) { + var upAnim, downAnim, refValue, + element = $( this ), + + // Defaults: + mode = options.mode, + hide = mode === "hide", + show = mode === "show", + direction = options.direction || "up", + distance = options.distance, + times = options.times || 5, + + // Number of internal animations + anims = times * 2 + ( show || hide ? 1 : 0 ), + speed = options.duration / anims, + easing = options.easing, + + // Utility: + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ), + i = 0, + + queuelen = element.queue().length; + + $.effects.createPlaceholder( element ); + + refValue = element.css( ref ); + + // Default distance for the BIGGEST bounce is the outer Distance / 3 + if ( !distance ) { + distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; + } + + if ( show ) { + downAnim = { opacity: 1 }; + downAnim[ ref ] = refValue; + + // If we are showing, force opacity 0 and set the initial position + // then do the "first" animation + element + .css( "opacity", 0 ) + .css( ref, motion ? -distance * 2 : distance * 2 ) + .animate( downAnim, speed, easing ); + } + + // Start at the smallest distance if we are hiding + if ( hide ) { + distance = distance / Math.pow( 2, times - 1 ); + } + + downAnim = {}; + downAnim[ ref ] = refValue; + + // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here + for ( ; i < times; i++ ) { + upAnim = {}; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + element + .animate( upAnim, speed, easing ) + .animate( downAnim, speed, easing ); + + distance = hide ? distance * 2 : distance / 2; + } + + // Last Bounce when Hiding + if ( hide ) { + upAnim = { opacity: 0 }; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + element.animate( upAnim, speed, easing ); + } + + element.queue( done ); + + $.effects.unshift( element, queuelen, anims + 1 ); +} ); + + +/*! + * jQuery UI Effects Clip 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Clip Effect +//>>group: Effects +//>>description: Clips the element on and off like an old TV. +//>>docs: http://api.jqueryui.com/clip-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) { + var start, + animate = {}, + element = $( this ), + direction = options.direction || "vertical", + both = direction === "both", + horizontal = both || direction === "horizontal", + vertical = both || direction === "vertical"; + + start = element.cssClip(); + animate.clip = { + top: vertical ? ( start.bottom - start.top ) / 2 : start.top, + right: horizontal ? ( start.right - start.left ) / 2 : start.right, + bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom, + left: horizontal ? ( start.right - start.left ) / 2 : start.left + }; + + $.effects.createPlaceholder( element ); + + if ( options.mode === "show" ) { + element.cssClip( animate.clip ); + animate.clip = start; + } + + element.animate( animate, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); + +} ); + + +/*! + * jQuery UI Effects Drop 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Drop Effect +//>>group: Effects +//>>description: Moves an element in one direction and hides it at the same time. +//>>docs: http://api.jqueryui.com/drop-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) { + + var distance, + element = $( this ), + mode = options.mode, + show = mode === "show", + direction = options.direction || "left", + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=", + oppositeMotion = ( motion === "+=" ) ? "-=" : "+=", + animation = { + opacity: 0 + }; + + $.effects.createPlaceholder( element ); + + distance = options.distance || + element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; + + animation[ ref ] = motion + distance; + + if ( show ) { + element.css( animation ); + + animation[ ref ] = oppositeMotion + distance; + animation.opacity = 1; + } + + // Animate + element.animate( animation, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Explode 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Explode Effect +//>>group: Effects +// jscs:disable maximumLineLength +//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness. +// jscs:enable maximumLineLength +//>>docs: http://api.jqueryui.com/explode-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) { + + var i, j, left, top, mx, my, + rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3, + cells = rows, + element = $( this ), + mode = options.mode, + show = mode === "show", + + // Show and then visibility:hidden the element before calculating offset + offset = element.show().css( "visibility", "hidden" ).offset(), + + // Width and height of a piece + width = Math.ceil( element.outerWidth() / cells ), + height = Math.ceil( element.outerHeight() / rows ), + pieces = []; + + // Children animate complete: + function childComplete() { + pieces.push( this ); + if ( pieces.length === rows * cells ) { + animComplete(); + } + } + + // Clone the element for each row and cell. + for ( i = 0; i < rows; i++ ) { // ===> + top = offset.top + i * height; + my = i - ( rows - 1 ) / 2; + + for ( j = 0; j < cells; j++ ) { // ||| + left = offset.left + j * width; + mx = j - ( cells - 1 ) / 2; + + // Create a clone of the now hidden main element that will be absolute positioned + // within a wrapper div off the -left and -top equal to size of our pieces + element + .clone() + .appendTo( "body" ) + .wrap( "
" ) + .css( { + position: "absolute", + visibility: "visible", + left: -j * width, + top: -i * height + } ) + + // Select the wrapper - make it overflow: hidden and absolute positioned based on + // where the original was located +left and +top equal to the size of pieces + .parent() + .addClass( "ui-effects-explode" ) + .css( { + position: "absolute", + overflow: "hidden", + width: width, + height: height, + left: left + ( show ? mx * width : 0 ), + top: top + ( show ? my * height : 0 ), + opacity: show ? 0 : 1 + } ) + .animate( { + left: left + ( show ? 0 : mx * width ), + top: top + ( show ? 0 : my * height ), + opacity: show ? 1 : 0 + }, options.duration || 500, options.easing, childComplete ); + } + } + + function animComplete() { + element.css( { + visibility: "visible" + } ); + $( pieces ).remove(); + done(); + } +} ); + + +/*! + * jQuery UI Effects Fade 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Fade Effect +//>>group: Effects +//>>description: Fades the element. +//>>docs: http://api.jqueryui.com/fade-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) { + var show = options.mode === "show"; + + $( this ) + .css( "opacity", show ? 0 : 1 ) + .animate( { + opacity: show ? 1 : 0 + }, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Fold 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Fold Effect +//>>group: Effects +//>>description: Folds an element first horizontally and then vertically. +//>>docs: http://api.jqueryui.com/fold-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) { + + // Create element + var element = $( this ), + mode = options.mode, + show = mode === "show", + hide = mode === "hide", + size = options.size || 15, + percent = /([0-9]+)%/.exec( size ), + horizFirst = !!options.horizFirst, + ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ], + duration = options.duration / 2, + + placeholder = $.effects.createPlaceholder( element ), + + start = element.cssClip(), + animation1 = { clip: $.extend( {}, start ) }, + animation2 = { clip: $.extend( {}, start ) }, + + distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ], + + queuelen = element.queue().length; + + if ( percent ) { + size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; + } + animation1.clip[ ref[ 0 ] ] = size; + animation2.clip[ ref[ 0 ] ] = size; + animation2.clip[ ref[ 1 ] ] = 0; + + if ( show ) { + element.cssClip( animation2.clip ); + if ( placeholder ) { + placeholder.css( $.effects.clipToBox( animation2 ) ); + } + + animation2.clip = start; + } + + // Animate + element + .queue( function( next ) { + if ( placeholder ) { + placeholder + .animate( $.effects.clipToBox( animation1 ), duration, options.easing ) + .animate( $.effects.clipToBox( animation2 ), duration, options.easing ); + } + + next(); + } ) + .animate( animation1, duration, options.easing ) + .animate( animation2, duration, options.easing ) + .queue( done ); + + $.effects.unshift( element, queuelen, 4 ); +} ); + + +/*! + * jQuery UI Effects Highlight 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Highlight Effect +//>>group: Effects +//>>description: Highlights the background of an element in a defined color for a custom duration. +//>>docs: http://api.jqueryui.com/highlight-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) { + var element = $( this ), + animation = { + backgroundColor: element.css( "backgroundColor" ) + }; + + if ( options.mode === "hide" ) { + animation.opacity = 0; + } + + $.effects.saveStyle( element ); + + element + .css( { + backgroundImage: "none", + backgroundColor: options.color || "#ffff99" + } ) + .animate( animation, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Size 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Size Effect +//>>group: Effects +//>>description: Resize an element to a specified width and height. +//>>docs: http://api.jqueryui.com/size-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectSize = $.effects.define( "size", function( options, done ) { + + // Create element + var baseline, factor, temp, + element = $( this ), + + // Copy for children + cProps = [ "fontSize" ], + vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], + hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], + + // Set options + mode = options.mode, + restore = mode !== "effect", + scale = options.scale || "both", + origin = options.origin || [ "middle", "center" ], + position = element.css( "position" ), + pos = element.position(), + original = $.effects.scaledDimensions( element ), + from = options.from || original, + to = options.to || $.effects.scaledDimensions( element, 0 ); + + $.effects.createPlaceholder( element ); + + if ( mode === "show" ) { + temp = from; + from = to; + to = temp; + } + + // Set scaling factor + factor = { + from: { + y: from.height / original.height, + x: from.width / original.width + }, + to: { + y: to.height / original.height, + x: to.width / original.width + } + }; + + // Scale the css box + if ( scale === "box" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + from = $.effects.setTransition( element, vProps, factor.from.y, from ); + to = $.effects.setTransition( element, vProps, factor.to.y, to ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + from = $.effects.setTransition( element, hProps, factor.from.x, from ); + to = $.effects.setTransition( element, hProps, factor.to.x, to ); + } + } + + // Scale the content + if ( scale === "content" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + from = $.effects.setTransition( element, cProps, factor.from.y, from ); + to = $.effects.setTransition( element, cProps, factor.to.y, to ); + } + } + + // Adjust the position properties based on the provided origin points + if ( origin ) { + baseline = $.effects.getBaseline( origin, original ); + from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top; + from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left; + to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top; + to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left; + } + element.css( from ); + + // Animate the children if desired + if ( scale === "content" || scale === "both" ) { + + vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps ); + hProps = hProps.concat( [ "marginLeft", "marginRight" ] ); + + // Only animate children with width attributes specified + // TODO: is this right? should we include anything with css width specified as well + element.find( "*[width]" ).each( function() { + var child = $( this ), + childOriginal = $.effects.scaledDimensions( child ), + childFrom = { + height: childOriginal.height * factor.from.y, + width: childOriginal.width * factor.from.x, + outerHeight: childOriginal.outerHeight * factor.from.y, + outerWidth: childOriginal.outerWidth * factor.from.x + }, + childTo = { + height: childOriginal.height * factor.to.y, + width: childOriginal.width * factor.to.x, + outerHeight: childOriginal.height * factor.to.y, + outerWidth: childOriginal.width * factor.to.x + }; + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom ); + childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom ); + childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo ); + } + + if ( restore ) { + $.effects.saveStyle( child ); + } + + // Animate children + child.css( childFrom ); + child.animate( childTo, options.duration, options.easing, function() { + + // Restore children + if ( restore ) { + $.effects.restoreStyle( child ); + } + } ); + } ); + } + + // Animate + element.animate( to, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: function() { + + var offset = element.offset(); + + if ( to.opacity === 0 ) { + element.css( "opacity", from.opacity ); + } + + if ( !restore ) { + element + .css( "position", position === "static" ? "relative" : position ) + .offset( offset ); + + // Need to save style here so that automatic style restoration + // doesn't restore to the original styles from before the animation. + $.effects.saveStyle( element ); + } + + done(); + } + } ); + +} ); + + +/*! + * jQuery UI Effects Scale 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Scale Effect +//>>group: Effects +//>>description: Grows or shrinks an element and its content. +//>>docs: http://api.jqueryui.com/scale-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectScale = $.effects.define( "scale", function( options, done ) { + + // Create element + var el = $( this ), + mode = options.mode, + percent = parseInt( options.percent, 10 ) || + ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ), + + newOptions = $.extend( true, { + from: $.effects.scaledDimensions( el ), + to: $.effects.scaledDimensions( el, percent, options.direction || "both" ), + origin: options.origin || [ "middle", "center" ] + }, options ); + + // Fade option to support puff + if ( options.fade ) { + newOptions.from.opacity = 1; + newOptions.to.opacity = 0; + } + + $.effects.effect.size.call( this, newOptions, done ); +} ); + + +/*! + * jQuery UI Effects Puff 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Puff Effect +//>>group: Effects +//>>description: Creates a puff effect by scaling the element up and hiding it at the same time. +//>>docs: http://api.jqueryui.com/puff-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) { + var newOptions = $.extend( true, {}, options, { + fade: true, + percent: parseInt( options.percent, 10 ) || 150 + } ); + + $.effects.effect.scale.call( this, newOptions, done ); +} ); + + +/*! + * jQuery UI Effects Pulsate 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Pulsate Effect +//>>group: Effects +//>>description: Pulsates an element n times by changing the opacity to zero and back. +//>>docs: http://api.jqueryui.com/pulsate-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) { + var element = $( this ), + mode = options.mode, + show = mode === "show", + hide = mode === "hide", + showhide = show || hide, + + // Showing or hiding leaves off the "last" animation + anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), + duration = options.duration / anims, + animateTo = 0, + i = 1, + queuelen = element.queue().length; + + if ( show || !element.is( ":visible" ) ) { + element.css( "opacity", 0 ).show(); + animateTo = 1; + } + + // Anims - 1 opacity "toggles" + for ( ; i < anims; i++ ) { + element.animate( { opacity: animateTo }, duration, options.easing ); + animateTo = 1 - animateTo; + } + + element.animate( { opacity: animateTo }, duration, options.easing ); + + element.queue( done ); + + $.effects.unshift( element, queuelen, anims + 1 ); +} ); + + +/*! + * jQuery UI Effects Shake 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Shake Effect +//>>group: Effects +//>>description: Shakes an element horizontally or vertically n times. +//>>docs: http://api.jqueryui.com/shake-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectShake = $.effects.define( "shake", function( options, done ) { + + var i = 1, + element = $( this ), + direction = options.direction || "left", + distance = options.distance || 20, + times = options.times || 3, + anims = times * 2 + 1, + speed = Math.round( options.duration / anims ), + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + positiveMotion = ( direction === "up" || direction === "left" ), + animation = {}, + animation1 = {}, + animation2 = {}, + + queuelen = element.queue().length; + + $.effects.createPlaceholder( element ); + + // Animation + animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; + animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; + animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; + + // Animate + element.animate( animation, speed, options.easing ); + + // Shakes + for ( ; i < times; i++ ) { + element + .animate( animation1, speed, options.easing ) + .animate( animation2, speed, options.easing ); + } + + element + .animate( animation1, speed, options.easing ) + .animate( animation, speed / 2, options.easing ) + .queue( done ); + + $.effects.unshift( element, queuelen, anims + 1 ); +} ); + + +/*! + * jQuery UI Effects Slide 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Slide Effect +//>>group: Effects +//>>description: Slides an element in and out of the viewport. +//>>docs: http://api.jqueryui.com/slide-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) { + var startClip, startRef, + element = $( this ), + map = { + up: [ "bottom", "top" ], + down: [ "top", "bottom" ], + left: [ "right", "left" ], + right: [ "left", "right" ] + }, + mode = options.mode, + direction = options.direction || "left", + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + positiveMotion = ( direction === "up" || direction === "left" ), + distance = options.distance || + element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ), + animation = {}; + + $.effects.createPlaceholder( element ); + + startClip = element.cssClip(); + startRef = element.position()[ ref ]; + + // Define hide animation + animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef; + animation.clip = element.cssClip(); + animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ]; + + // Reverse the animation if we're showing + if ( mode === "show" ) { + element.cssClip( animation.clip ); + element.css( ref, animation[ ref ] ); + animation.clip = startClip; + animation[ ref ] = startRef; + } + + // Actually animate + element.animate( animation, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Transfer 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Transfer Effect +//>>group: Effects +//>>description: Displays a transfer effect from one element to another. +//>>docs: http://api.jqueryui.com/transfer-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effect; +if ( $.uiBackCompat !== false ) { + effect = $.effects.define( "transfer", function( options, done ) { + $( this ).transfer( options, done ); + } ); +} +var effectsEffectTransfer = effect; + + +/*! + * jQuery UI Focusable 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: :focusable Selector +//>>group: Core +//>>description: Selects elements which can be focused. +//>>docs: http://api.jqueryui.com/focusable-selector/ + + + +// Selectors +$.ui.focusable = function( element, hasTabindex ) { + var map, mapName, img, focusableIfVisible, fieldset, + nodeName = element.nodeName.toLowerCase(); + + if ( "area" === nodeName ) { + map = element.parentNode; + mapName = map.name; + if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { + return false; + } + img = $( "img[usemap='#" + mapName + "']" ); + return img.length > 0 && img.is( ":visible" ); + } + + if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) { + focusableIfVisible = !element.disabled; + + if ( focusableIfVisible ) { + + // Form controls within a disabled fieldset are disabled. + // However, controls within the fieldset's legend do not get disabled. + // Since controls generally aren't placed inside legends, we skip + // this portion of the check. + fieldset = $( element ).closest( "fieldset" )[ 0 ]; + if ( fieldset ) { + focusableIfVisible = !fieldset.disabled; + } + } + } else if ( "a" === nodeName ) { + focusableIfVisible = element.href || hasTabindex; + } else { + focusableIfVisible = hasTabindex; + } + + return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) ); +}; + +// Support: IE 8 only +// IE 8 doesn't resolve inherit to visible/hidden for computed values +function visible( element ) { + var visibility = element.css( "visibility" ); + while ( visibility === "inherit" ) { + element = element.parent(); + visibility = element.css( "visibility" ); + } + return visibility !== "hidden"; +} + +$.extend( $.expr[ ":" ], { + focusable: function( element ) { + return $.ui.focusable( element, $.attr( element, "tabindex" ) != null ); + } +} ); + +var focusable = $.ui.focusable; + + + + +// Support: IE8 Only +// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop +// with a string, so we need to find the proper form. +var form = $.fn.form = function() { + return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form ); +}; + + +/*! + * jQuery UI Form Reset Mixin 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Form Reset Mixin +//>>group: Core +//>>description: Refresh input widgets when their form is reset +//>>docs: http://api.jqueryui.com/form-reset-mixin/ + + + +var formResetMixin = $.ui.formResetMixin = { + _formResetHandler: function() { + var form = $( this ); + + // Wait for the form reset to actually happen before refreshing + setTimeout( function() { + var instances = form.data( "ui-form-reset-instances" ); + $.each( instances, function() { + this.refresh(); + } ); + } ); + }, + + _bindFormResetHandler: function() { + this.form = this.element.form(); + if ( !this.form.length ) { + return; + } + + var instances = this.form.data( "ui-form-reset-instances" ) || []; + if ( !instances.length ) { + + // We don't use _on() here because we use a single event handler per form + this.form.on( "reset.ui-form-reset", this._formResetHandler ); + } + instances.push( this ); + this.form.data( "ui-form-reset-instances", instances ); + }, + + _unbindFormResetHandler: function() { + if ( !this.form.length ) { + return; + } + + var instances = this.form.data( "ui-form-reset-instances" ); + instances.splice( $.inArray( this, instances ), 1 ); + if ( instances.length ) { + this.form.data( "ui-form-reset-instances", instances ); + } else { + this.form + .removeData( "ui-form-reset-instances" ) + .off( "reset.ui-form-reset" ); + } + } +}; + + +/*! + * jQuery UI Support for jQuery core 1.7.x 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + */ + +//>>label: jQuery 1.7 Support +//>>group: Core +//>>description: Support version 1.7.x of jQuery core + + + +// Support: jQuery 1.7 only +// Not a great way to check versions, but since we only support 1.7+ and only +// need to detect <1.8, this is a simple check that should suffice. Checking +// for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0 +// and we'll never reach 1.70.0 (if we do, we certainly won't be supporting +// 1.7 anymore). See #11197 for why we're not using feature detection. +if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) { + + // Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight() + // Unlike jQuery Core 1.8+, these only support numeric values to set the + // dimensions in pixels + $.each( [ "Width", "Height" ], function( i, name ) { + var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], + type = name.toLowerCase(), + orig = { + innerWidth: $.fn.innerWidth, + innerHeight: $.fn.innerHeight, + outerWidth: $.fn.outerWidth, + outerHeight: $.fn.outerHeight + }; + + function reduce( elem, size, border, margin ) { + $.each( side, function() { + size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; + if ( border ) { + size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; + } + if ( margin ) { + size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; + } + } ); + return size; + } + + $.fn[ "inner" + name ] = function( size ) { + if ( size === undefined ) { + return orig[ "inner" + name ].call( this ); + } + + return this.each( function() { + $( this ).css( type, reduce( this, size ) + "px" ); + } ); + }; + + $.fn[ "outer" + name ] = function( size, margin ) { + if ( typeof size !== "number" ) { + return orig[ "outer" + name ].call( this, size ); + } + + return this.each( function() { + $( this ).css( type, reduce( this, size, true, margin ) + "px" ); + } ); + }; + } ); + + $.fn.addBack = function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + }; +} + +; +/*! + * jQuery UI Keycode 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Keycode +//>>group: Core +//>>description: Provide keycodes as keynames +//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/ + + +var keycode = $.ui.keyCode = { + BACKSPACE: 8, + COMMA: 188, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + LEFT: 37, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SPACE: 32, + TAB: 9, + UP: 38 +}; + + + + +// Internal use only +var escapeSelector = $.ui.escapeSelector = ( function() { + var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g; + return function( selector ) { + return selector.replace( selectorEscape, "\\$1" ); + }; +} )(); + + +/*! + * jQuery UI Labels 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: labels +//>>group: Core +//>>description: Find all the labels associated with a given input +//>>docs: http://api.jqueryui.com/labels/ + + + +var labels = $.fn.labels = function() { + var ancestor, selector, id, labels, ancestors; + + // Check control.labels first + if ( this[ 0 ].labels && this[ 0 ].labels.length ) { + return this.pushStack( this[ 0 ].labels ); + } + + // Support: IE <= 11, FF <= 37, Android <= 2.3 only + // Above browsers do not support control.labels. Everything below is to support them + // as well as document fragments. control.labels does not work on document fragments + labels = this.eq( 0 ).parents( "label" ); + + // Look for the label based on the id + id = this.attr( "id" ); + if ( id ) { + + // We don't search against the document in case the element + // is disconnected from the DOM + ancestor = this.eq( 0 ).parents().last(); + + // Get a full set of top level ancestors + ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); + + // Create a selector for the label based on the id + selector = "label[for='" + $.ui.escapeSelector( id ) + "']"; + + labels = labels.add( ancestors.find( selector ).addBack( selector ) ); + + } + + // Return whatever we have found for labels + return this.pushStack( labels ); +}; + + +/*! + * jQuery UI Scroll Parent 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: scrollParent +//>>group: Core +//>>description: Get the closest ancestor element that is scrollable. +//>>docs: http://api.jqueryui.com/scrollParent/ + + + +var scrollParent = $.fn.scrollParent = function( includeHidden ) { + var position = this.css( "position" ), + excludeStaticParent = position === "absolute", + overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, + scrollParent = this.parents().filter( function() { + var parent = $( this ); + if ( excludeStaticParent && parent.css( "position" ) === "static" ) { + return false; + } + return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + + parent.css( "overflow-x" ) ); + } ).eq( 0 ); + + return position === "fixed" || !scrollParent.length ? + $( this[ 0 ].ownerDocument || document ) : + scrollParent; +}; + + +/*! + * jQuery UI Tabbable 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: :tabbable Selector +//>>group: Core +//>>description: Selects elements which can be tabbed to. +//>>docs: http://api.jqueryui.com/tabbable-selector/ + + + +var tabbable = $.extend( $.expr[ ":" ], { + tabbable: function( element ) { + var tabIndex = $.attr( element, "tabindex" ), + hasTabindex = tabIndex != null; + return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex ); + } +} ); + + +/*! + * jQuery UI Unique ID 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: uniqueId +//>>group: Core +//>>description: Functions to generate and remove uniqueId's +//>>docs: http://api.jqueryui.com/uniqueId/ + + + +var uniqueId = $.fn.extend( { + uniqueId: ( function() { + var uuid = 0; + + return function() { + return this.each( function() { + if ( !this.id ) { + this.id = "ui-id-" + ( ++uuid ); + } + } ); + }; + } )(), + + removeUniqueId: function() { + return this.each( function() { + if ( /^ui-id-\d+$/.test( this.id ) ) { + $( this ).removeAttr( "id" ); + } + } ); + } +} ); + + +/*! + * jQuery UI Accordion 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Accordion +//>>group: Widgets +// jscs:disable maximumLineLength +//>>description: Displays collapsible content panels for presenting information in a limited amount of space. +// jscs:enable maximumLineLength +//>>docs: http://api.jqueryui.com/accordion/ +//>>demos: http://jqueryui.com/accordion/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/accordion.css +//>>css.theme: ../../themes/base/theme.css + + + +var widgetsAccordion = $.widget( "ui.accordion", { + version: "1.12.1", + options: { + active: 0, + animate: {}, + classes: { + "ui-accordion-header": "ui-corner-top", + "ui-accordion-header-collapsed": "ui-corner-all", + "ui-accordion-content": "ui-corner-bottom" + }, + collapsible: false, + event: "click", + header: "> li > :first-child, > :not(li):even", + heightStyle: "auto", + icons: { + activeHeader: "ui-icon-triangle-1-s", + header: "ui-icon-triangle-1-e" + }, + + // Callbacks + activate: null, + beforeActivate: null + }, + + hideProps: { + borderTopWidth: "hide", + borderBottomWidth: "hide", + paddingTop: "hide", + paddingBottom: "hide", + height: "hide" + }, + + showProps: { + borderTopWidth: "show", + borderBottomWidth: "show", + paddingTop: "show", + paddingBottom: "show", + height: "show" + }, + + _create: function() { + var options = this.options; + + this.prevShow = this.prevHide = $(); + this._addClass( "ui-accordion", "ui-widget ui-helper-reset" ); + this.element.attr( "role", "tablist" ); + + // Don't allow collapsible: false and active: false / null + if ( !options.collapsible && ( options.active === false || options.active == null ) ) { + options.active = 0; + } + + this._processPanels(); + + // handle negative values + if ( options.active < 0 ) { + options.active += this.headers.length; + } + this._refresh(); + }, + + _getCreateEventData: function() { + return { + header: this.active, + panel: !this.active.length ? $() : this.active.next() + }; + }, + + _createIcons: function() { + var icon, children, + icons = this.options.icons; + + if ( icons ) { + icon = $( "" ); + this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header ); + icon.prependTo( this.headers ); + children = this.active.children( ".ui-accordion-header-icon" ); + this._removeClass( children, icons.header ) + ._addClass( children, null, icons.activeHeader ) + ._addClass( this.headers, "ui-accordion-icons" ); + } + }, + + _destroyIcons: function() { + this._removeClass( this.headers, "ui-accordion-icons" ); + this.headers.children( ".ui-accordion-header-icon" ).remove(); + }, + + _destroy: function() { + var contents; + + // Clean up main element + this.element.removeAttr( "role" ); + + // Clean up headers + this.headers + .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" ) + .removeUniqueId(); + + this._destroyIcons(); + + // Clean up content panels + contents = this.headers.next() + .css( "display", "" ) + .removeAttr( "role aria-hidden aria-labelledby" ) + .removeUniqueId(); + + if ( this.options.heightStyle !== "content" ) { + contents.css( "height", "" ); + } + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + if ( key === "event" ) { + if ( this.options.event ) { + this._off( this.headers, this.options.event ); + } + this._setupEvents( value ); + } + + this._super( key, value ); + + // Setting collapsible: false while collapsed; open first panel + if ( key === "collapsible" && !value && this.options.active === false ) { + this._activate( 0 ); + } + + if ( key === "icons" ) { + this._destroyIcons(); + if ( value ) { + this._createIcons(); + } + } + }, + + _setOptionDisabled: function( value ) { + this._super( value ); + + this.element.attr( "aria-disabled", value ); + + // Support: IE8 Only + // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE + // so we need to add the disabled class to the headers and panels + this._toggleClass( null, "ui-state-disabled", !!value ); + this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled", + !!value ); + }, + + _keydown: function( event ) { + if ( event.altKey || event.ctrlKey ) { + return; + } + + var keyCode = $.ui.keyCode, + length = this.headers.length, + currentIndex = this.headers.index( event.target ), + toFocus = false; + + switch ( event.keyCode ) { + case keyCode.RIGHT: + case keyCode.DOWN: + toFocus = this.headers[ ( currentIndex + 1 ) % length ]; + break; + case keyCode.LEFT: + case keyCode.UP: + toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; + break; + case keyCode.SPACE: + case keyCode.ENTER: + this._eventHandler( event ); + break; + case keyCode.HOME: + toFocus = this.headers[ 0 ]; + break; + case keyCode.END: + toFocus = this.headers[ length - 1 ]; + break; + } + + if ( toFocus ) { + $( event.target ).attr( "tabIndex", -1 ); + $( toFocus ).attr( "tabIndex", 0 ); + $( toFocus ).trigger( "focus" ); + event.preventDefault(); + } + }, + + _panelKeyDown: function( event ) { + if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { + $( event.currentTarget ).prev().trigger( "focus" ); + } + }, + + refresh: function() { + var options = this.options; + this._processPanels(); + + // Was collapsed or no panel + if ( ( options.active === false && options.collapsible === true ) || + !this.headers.length ) { + options.active = false; + this.active = $(); + + // active false only when collapsible is true + } else if ( options.active === false ) { + this._activate( 0 ); + + // was active, but active panel is gone + } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { + + // all remaining panel are disabled + if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) { + options.active = false; + this.active = $(); + + // activate previous panel + } else { + this._activate( Math.max( 0, options.active - 1 ) ); + } + + // was active, active panel still exists + } else { + + // make sure active index is correct + options.active = this.headers.index( this.active ); + } + + this._destroyIcons(); + + this._refresh(); + }, + + _processPanels: function() { + var prevHeaders = this.headers, + prevPanels = this.panels; + + this.headers = this.element.find( this.options.header ); + this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", + "ui-state-default" ); + + this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide(); + this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" ); + + // Avoid memory leaks (#10056) + if ( prevPanels ) { + this._off( prevHeaders.not( this.headers ) ); + this._off( prevPanels.not( this.panels ) ); + } + }, + + _refresh: function() { + var maxHeight, + options = this.options, + heightStyle = options.heightStyle, + parent = this.element.parent(); + + this.active = this._findActive( options.active ); + this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" ) + ._removeClass( this.active, "ui-accordion-header-collapsed" ); + this._addClass( this.active.next(), "ui-accordion-content-active" ); + this.active.next().show(); + + this.headers + .attr( "role", "tab" ) + .each( function() { + var header = $( this ), + headerId = header.uniqueId().attr( "id" ), + panel = header.next(), + panelId = panel.uniqueId().attr( "id" ); + header.attr( "aria-controls", panelId ); + panel.attr( "aria-labelledby", headerId ); + } ) + .next() + .attr( "role", "tabpanel" ); + + this.headers + .not( this.active ) + .attr( { + "aria-selected": "false", + "aria-expanded": "false", + tabIndex: -1 + } ) + .next() + .attr( { + "aria-hidden": "true" + } ) + .hide(); + + // Make sure at least one header is in the tab order + if ( !this.active.length ) { + this.headers.eq( 0 ).attr( "tabIndex", 0 ); + } else { + this.active.attr( { + "aria-selected": "true", + "aria-expanded": "true", + tabIndex: 0 + } ) + .next() + .attr( { + "aria-hidden": "false" + } ); + } + + this._createIcons(); + + this._setupEvents( options.event ); + + if ( heightStyle === "fill" ) { + maxHeight = parent.height(); + this.element.siblings( ":visible" ).each( function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + } ); + + this.headers.each( function() { + maxHeight -= $( this ).outerHeight( true ); + } ); + + this.headers.next() + .each( function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + } ) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.headers.next() + .each( function() { + var isVisible = $( this ).is( ":visible" ); + if ( !isVisible ) { + $( this ).show(); + } + maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); + if ( !isVisible ) { + $( this ).hide(); + } + } ) + .height( maxHeight ); + } + }, + + _activate: function( index ) { + var active = this._findActive( index )[ 0 ]; + + // Trying to activate the already active panel + if ( active === this.active[ 0 ] ) { + return; + } + + // Trying to collapse, simulate a click on the currently active header + active = active || this.active[ 0 ]; + + this._eventHandler( { + target: active, + currentTarget: active, + preventDefault: $.noop + } ); + }, + + _findActive: function( selector ) { + return typeof selector === "number" ? this.headers.eq( selector ) : $(); + }, + + _setupEvents: function( event ) { + var events = { + keydown: "_keydown" + }; + if ( event ) { + $.each( event.split( " " ), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + } ); + } + + this._off( this.headers.add( this.headers.next() ) ); + this._on( this.headers, events ); + this._on( this.headers.next(), { keydown: "_panelKeyDown" } ); + this._hoverable( this.headers ); + this._focusable( this.headers ); + }, + + _eventHandler: function( event ) { + var activeChildren, clickedChildren, + options = this.options, + active = this.active, + clicked = $( event.currentTarget ), + clickedIsActive = clicked[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : clicked.next(), + toHide = active.next(), + eventData = { + oldHeader: active, + oldPanel: toHide, + newHeader: collapsing ? $() : clicked, + newPanel: toShow + }; + + event.preventDefault(); + + if ( + + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; + } + + options.active = collapsing ? false : this.headers.index( clicked ); + + // When the call to ._toggle() comes after the class changes + // it causes a very odd bug in IE 8 (see #6720) + this.active = clickedIsActive ? $() : clicked; + this._toggle( eventData ); + + // Switch classes + // corner classes on the previously active header stay after the animation + this._removeClass( active, "ui-accordion-header-active", "ui-state-active" ); + if ( options.icons ) { + activeChildren = active.children( ".ui-accordion-header-icon" ); + this._removeClass( activeChildren, null, options.icons.activeHeader ) + ._addClass( activeChildren, null, options.icons.header ); + } + + if ( !clickedIsActive ) { + this._removeClass( clicked, "ui-accordion-header-collapsed" ) + ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" ); + if ( options.icons ) { + clickedChildren = clicked.children( ".ui-accordion-header-icon" ); + this._removeClass( clickedChildren, null, options.icons.header ) + ._addClass( clickedChildren, null, options.icons.activeHeader ); + } + + this._addClass( clicked.next(), "ui-accordion-content-active" ); + } + }, + + _toggle: function( data ) { + var toShow = data.newPanel, + toHide = this.prevShow.length ? this.prevShow : data.oldPanel; + + // Handle activating a panel during the animation for another activation + this.prevShow.add( this.prevHide ).stop( true, true ); + this.prevShow = toShow; + this.prevHide = toHide; + + if ( this.options.animate ) { + this._animate( toShow, toHide, data ); + } else { + toHide.hide(); + toShow.show(); + this._toggleComplete( data ); + } + + toHide.attr( { + "aria-hidden": "true" + } ); + toHide.prev().attr( { + "aria-selected": "false", + "aria-expanded": "false" + } ); + + // if we're switching panels, remove the old header from the tab order + // if we're opening from collapsed state, remove the previous header from the tab order + // if we're collapsing, then keep the collapsing header in the tab order + if ( toShow.length && toHide.length ) { + toHide.prev().attr( { + "tabIndex": -1, + "aria-expanded": "false" + } ); + } else if ( toShow.length ) { + this.headers.filter( function() { + return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; + } ) + .attr( "tabIndex", -1 ); + } + + toShow + .attr( "aria-hidden", "false" ) + .prev() + .attr( { + "aria-selected": "true", + "aria-expanded": "true", + tabIndex: 0 + } ); + }, + + _animate: function( toShow, toHide, data ) { + var total, easing, duration, + that = this, + adjust = 0, + boxSizing = toShow.css( "box-sizing" ), + down = toShow.length && + ( !toHide.length || ( toShow.index() < toHide.index() ) ), + animate = this.options.animate || {}, + options = down && animate.down || animate, + complete = function() { + that._toggleComplete( data ); + }; + + if ( typeof options === "number" ) { + duration = options; + } + if ( typeof options === "string" ) { + easing = options; + } + + // fall back from options to animation in case of partial down settings + easing = easing || options.easing || animate.easing; + duration = duration || options.duration || animate.duration; + + if ( !toHide.length ) { + return toShow.animate( this.showProps, duration, easing, complete ); + } + if ( !toShow.length ) { + return toHide.animate( this.hideProps, duration, easing, complete ); + } + + total = toShow.show().outerHeight(); + toHide.animate( this.hideProps, { + duration: duration, + easing: easing, + step: function( now, fx ) { + fx.now = Math.round( now ); + } + } ); + toShow + .hide() + .animate( this.showProps, { + duration: duration, + easing: easing, + complete: complete, + step: function( now, fx ) { + fx.now = Math.round( now ); + if ( fx.prop !== "height" ) { + if ( boxSizing === "content-box" ) { + adjust += fx.now; + } + } else if ( that.options.heightStyle !== "content" ) { + fx.now = Math.round( total - toHide.outerHeight() - adjust ); + adjust = 0; + } + } + } ); + }, + + _toggleComplete: function( data ) { + var toHide = data.oldPanel, + prev = toHide.prev(); + + this._removeClass( toHide, "ui-accordion-content-active" ); + this._removeClass( prev, "ui-accordion-header-active" ) + ._addClass( prev, "ui-accordion-header-collapsed" ); + + // Work around for rendering bug in IE (#5421) + if ( toHide.length ) { + toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className; + } + this._trigger( "activate", null, data ); + } +} ); + + + +var safeActiveElement = $.ui.safeActiveElement = function( document ) { + var activeElement; + + // Support: IE 9 only + // IE9 throws an "Unspecified error" accessing document.activeElement from an