From 61993c7e073aeee2ce4207a4be762cb00ac162d8 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Tue, 22 Apr 2014 16:25:34 -0500 Subject: [PATCH 01/27] adding some services and whatnot --- app/scripts/app.js | 1 + app/scripts/modules/betty-cropper.js | 63 ++++++++++++++++++++++++++ app/scripts/services/imagecropmodal.js | 25 ++++++++++ app/views/image-crop-modal.html | 1 + 4 files changed, 90 insertions(+) create mode 100644 app/scripts/modules/betty-cropper.js create mode 100644 app/scripts/services/imagecropmodal.js create mode 100644 app/views/image-crop-modal.html diff --git a/app/scripts/app.js b/app/scripts/app.js index cbde1a59a..3cef0a0dd 100644 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -17,6 +17,7 @@ angular.module('bulbsCmsApp', [ 'ngSanitize', 'ngRoute', 'ui.bootstrap', + 'bettyCropper', 'jquery', 'underscore', 'NProgress', diff --git a/app/scripts/modules/betty-cropper.js b/app/scripts/modules/betty-cropper.js new file mode 100644 index 000000000..76411b517 --- /dev/null +++ b/app/scripts/modules/betty-cropper.js @@ -0,0 +1,63 @@ +angular.module('bettyCropper', []) + .service('$bettycropper', function $bettycropper($http, IMAGE_SERVER_URL) { + this.detail = function (id) { + return $http({ + method: 'GET', + url: IMAGE_SERVER_URL + '/api/' + id, + headers: { + 'X-Betty-Api-Key': BC_API_KEY, + 'Content-Type': undefined + }, + transformRequest: angular.identity + }); + }; + + this.detail_patch = function (id, name, credit, selections) { + return $http({ + method: 'GET', + url: IMAGE_SERVER_URL + '/api/' + id, + headers: { + 'X-Betty-Api-Key': BC_API_KEY, + 'Content-Type': undefined + }, + data: { + name: name, + credit: credit, + selections: selections + }, + transformRequest: angular.identity + }); + }; + + this.new = function (image, name, credit) { + var imageData = new FormData(); + imageData.append('image', image); + if (name) { imageData.append('name', name); } + if (credit) { imageData.append('credit', credit); } + + return $http({ + method: 'POST', + url: IMAGE_SERVER_URL + '/api/new', + headers: { + 'X-Betty-Api-Key': BC_API_KEY, + 'Content-Type': undefined + }, + data: imageData, + transformRequest: angular.identity + }); + }; + + this.update_selection = function (id, ratio, selections) { + return $http({ + method: 'POST', + url: IMAGE_SERVER_URL + '/api/' + id + "/" + ratio, + headers: { + 'X-Betty-Api-Key': BC_API_KEY, + 'Content-Type': undefined + }, + data: selections, + transformRequest: angular.identity + }); + }; + + }); diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js new file mode 100644 index 000000000..0fdf041d5 --- /dev/null +++ b/app/scripts/services/imagecropmodal.js @@ -0,0 +1,25 @@ +'use strict'; + +angular.module('bulbsCmsApp') + .factory('openImageCropModal', function ($document, $compile, $rootScope) { + return function () { + var el = $compile("")($rootScope); + $document.find('body').append(el); + }; + }) + .directive('ngImageCropModal', function ($modal, $bettycropper, routes) { + return { + restrict: 'E', + scope: {}, + link: function (scope, element, attrs) { + var ModalInstanceCtrl = function ($scope, $modalInstance) { + + }; + $modal.open({ + templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", + controller: ModalInstanceCtrl + }); + } + }; + }); + diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html new file mode 100644 index 000000000..d531e8e05 --- /dev/null +++ b/app/views/image-crop-modal.html @@ -0,0 +1 @@ + From 916e317412b3a39cd1ab0edfa88b3474d24a844f Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Wed, 23 Apr 2014 18:30:08 -0500 Subject: [PATCH 02/27] adding a ton of shit --- app/scripts/modules/betty-cropper.js | 36 +++++++- app/scripts/services/imagecropmodal.js | 121 +++++++++++++++++++++++-- app/views/image-crop-modal.html | 23 ++++- 3 files changed, 171 insertions(+), 9 deletions(-) diff --git a/app/scripts/modules/betty-cropper.js b/app/scripts/modules/betty-cropper.js index 76411b517..30089a604 100644 --- a/app/scripts/modules/betty-cropper.js +++ b/app/scripts/modules/betty-cropper.js @@ -1,5 +1,12 @@ angular.module('bettyCropper', []) - .service('$bettycropper', function $bettycropper($http, IMAGE_SERVER_URL) { + .service('$bettycropper', function $bettycropper($http, $interpolate, IMAGE_SERVER_URL, BC_API_KEY) { + + /*\ + + Betty Cropper API + + \*/ + this.detail = function (id) { return $http({ method: 'GET', @@ -60,4 +67,31 @@ angular.module('bettyCropper', []) }); }; + /*\ + + Convenience Methods + + \*/ + + this.url = function (id, crop, width, format) { + var exp = $interpolate( + "{{ url }}/{{ id }}/{{ crop }}/{{ width }}.{{ format }}" + ); + return exp({ + url: IMAGE_SERVER_URL, + id: id, + crop: crop, + width: width, + format: format + }); + }; + + this.orig_jpg = function (id, width) { + return this.url(id, 'original', width, 'jpg'); + }; + + this.orig_gif = function (id, width) { + return this.url(id, 'original', width, 'gif'); + }; + }); diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index 0fdf041d5..2dd87d654 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -2,23 +2,130 @@ angular.module('bulbsCmsApp') .factory('openImageCropModal', function ($document, $compile, $rootScope) { - return function () { - var el = $compile("")($rootScope); + return function (id) { + var el = $compile( + "" + )($rootScope); $document.find('body').append(el); }; }) - .directive('ngImageCropModal', function ($modal, $bettycropper, routes) { + .directive('ngImageCropModal', function ($modal, routes) { return { restrict: 'E', - scope: {}, + scope: { + imageId: "=" + }, link: function (scope, element, attrs) { - var ModalInstanceCtrl = function ($scope, $modalInstance) { + var ModalInstanceCtrl = function ($scope, $interpolate, $bettycropper, $modalInstance, id) { + var jcrop_api; + $scope.thumb_width = 180; + $scope.crop_image_width = 550; + $scope.thumb_url = $bettycropper.orig_jpg(id, $scope.thumb_width); + $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); + + $bettycropper.detail(id) + .success(function (data) { + $scope.image = data; + $scope.computeRatioStyles($scope.image, $scope.image.selections); + + $('#crop-image').Jcrop({ + onSelect: function () {console.log('onSelect')}, + allowMove: true, + allowResize: true, + keySupport: false + }, function () { // Jcrop Init Callback + + // NOTE: Maybe 16x9 shouldn't be hard-coded? + + jcrop_api = this; + jcrop_api.setOptions({ + aspectRatio: 16/9 + }); + + var scale = $scope.crop_image_width / $scope.image.width; + var s = $scope.image.selections['16x9']; + jcrop_api.setSelect([ + $scope.scaleNumber(s.x0, scale), + $scope.scaleNumber(s.y0, scale), + $scope.scaleNumber(s.x1, scale), + $scope.scaleNumber(s.y1, scale) + ]); + + }); + + }); + + // Don't understand why I can't do currSelection = {ratio: selection} + // in the ng-click handler... + $scope.setCurrSelection = function (ratio, selection) { + $scope.currSelection = [ratio, selection]; + }; + + $scope.$watch('currSelection', function (newVal) { + if (typeof(newVal) === 'undefined') { return; } + + var scale = $scope.crop_image_width / $scope.image.width; + var selection = newVal[1]; + var ratioNums = newVal[0].split('x'); + + jcrop_api.setOptions({ + aspectRatio: ratioNums[0] / ratioNums[1] + }); + + jcrop_api.setSelect([ + $scope.scaleNumber(selection.x0, scale), + $scope.scaleNumber(selection.y0, scale), + $scope.scaleNumber(selection.x1, scale), + $scope.scaleNumber(selection.y1, scale) + ]); + }); + + $scope.computeRatioStyles = function (image, selections) { + $scope.ratio_styles = $scope.ratio_styles || {}; + var scale = $scope.thumb_width / image.width; + + for (var s in selections) { + var top, right, bottom, left; + + top = $scope.scaleNumber(selections[s].y0, scale); + left = $scope.scaleNumber(selections[s].x0, scale); + right = $scope.scaleNumber(image.width - selections[s].x1, scale); + bottom = $scope.scaleNumber(image.height - selections[s].y1, scale); + + var margin = '-'+top+'px -'+right+'px -'+bottom+'px -'+left+'px'; + + $scope.ratio_styles[s] = { + margin: margin + }; + } + }; + + $scope.scaleNumber = function (num, by_scale) { + return Math.floor(num * by_scale); + }; + + $scope.close = function () { + $modalInstance.close(); + }; + + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); + }; }; + $modal.open({ templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", - controller: ModalInstanceCtrl - }); + controller: ModalInstanceCtrl, + resolve: { + id: function () { return scope.imageId; } + } + }) + .result + .finally(function () { + element.remove(); + }) + } }; }); diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html index d531e8e05..f5b56c264 100644 --- a/app/views/image-crop-modal.html +++ b/app/views/image-crop-modal.html @@ -1 +1,22 @@ - +
+ + + +
From 9959cdae18043d004e57cb56ea3ea9690a3b5893 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Thu, 24 Apr 2014 16:44:45 -0500 Subject: [PATCH 03/27] just commiting --- app/scripts/modules/betty-cropper.js | 5 +- app/scripts/services/imagecropmodal.js | 169 +++++++++++++++++-------- app/views/image-crop-modal.html | 8 +- 3 files changed, 119 insertions(+), 63 deletions(-) diff --git a/app/scripts/modules/betty-cropper.js b/app/scripts/modules/betty-cropper.js index 30089a604..6cec91738 100644 --- a/app/scripts/modules/betty-cropper.js +++ b/app/scripts/modules/betty-cropper.js @@ -21,7 +21,7 @@ angular.module('bettyCropper', []) this.detail_patch = function (id, name, credit, selections) { return $http({ - method: 'GET', + method: 'PATCH', url: IMAGE_SERVER_URL + '/api/' + id, headers: { 'X-Betty-Api-Key': BC_API_KEY, @@ -62,8 +62,7 @@ angular.module('bettyCropper', []) 'X-Betty-Api-Key': BC_API_KEY, 'Content-Type': undefined }, - data: selections, - transformRequest: angular.identity + data: selections }); }; diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index 2dd87d654..03e72ed3d 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -17,52 +17,65 @@ angular.module('bulbsCmsApp') }, link: function (scope, element, attrs) { var ModalInstanceCtrl = function ($scope, $interpolate, $bettycropper, $modalInstance, id) { - var jcrop_api; + var jcrop_api, ratioOrder; $scope.thumb_width = 180; $scope.crop_image_width = 550; - $scope.thumb_url = $bettycropper.orig_jpg(id, $scope.thumb_width); - $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); - - $bettycropper.detail(id) - .success(function (data) { - $scope.image = data; - $scope.computeRatioStyles($scope.image, $scope.image.selections); - - $('#crop-image').Jcrop({ - onSelect: function () {console.log('onSelect')}, - allowMove: true, - allowResize: true, - keySupport: false - }, function () { // Jcrop Init Callback - - // NOTE: Maybe 16x9 shouldn't be hard-coded? - - jcrop_api = this; - jcrop_api.setOptions({ - aspectRatio: 16/9 - }); - - var scale = $scope.crop_image_width / $scope.image.width; - var s = $scope.image.selections['16x9']; - jcrop_api.setSelect([ - $scope.scaleNumber(s.x0, scale), - $scope.scaleNumber(s.y0, scale), - $scope.scaleNumber(s.x1, scale), - $scope.scaleNumber(s.y1, scale) - ]); - - }); + var setupCropperCallback = function (data) { + $scope.image = data; + // $scope.setCropStyle($scope.image); + $scope.setThumbStyles($scope.image, $scope.image.selections); + $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); + ratioOrder = Object.keys($scope.image.selections); + + $('#crop-image').Jcrop({ + allowSelect: false, + allowMove: true, + allowResize: true, + keySupport: false + }, function () { // Jcrop Init Callback + jcrop_api = this; + $scope.selectedCrop = [ + ratioOrder[0], + $scope.image.selections[ratioOrder[0]] + ]; }); + }; - // Don't understand why I can't do currSelection = {ratio: selection} + $scope.processJcropSelection = function (s) { + if ( + angular.isNumber(s.x) && !isNaN(s.x) || + angular.isNumber(s.y) && !isNaN(s.y) || + angular.isNumber(s.x2) && !isNaN(s.x2) || + angular.isNumber(s.y2) && !isNaN(s.y2) || + angular.isNumber(s.w) && !isNaN(s.w) || + angular.isNumber(s.h) && !isNaN(s.h) + ) { + var selection = {}; + + var scale = $scope.crop_image_width / $scope.image.width; + selection.x0 = $scope.scaleNumber(s.x, 1 / scale); + selection.y0 = $scope.scaleNumber(s.y, 1 / scale); + selection.x1 = $scope.scaleNumber(s.x2, 1 / scale); + selection.y1 = $scope.scaleNumber(s.y2, 1 / scale); + + $scope.image.selections[$scope.selectedCrop[0]] = selection; + $scope.computeThumbStyle( + $scope.image, + $scope.selectedCrop[0], + selection + ); + } + }; + + // Don't understand why I can't do selectedCrop = {ratio: selection} // in the ng-click handler... - $scope.setCurrSelection = function (ratio, selection) { - $scope.currSelection = [ratio, selection]; + $scope.setSelectedCrop = function (ratio, selection) { + $scope.selectedCrop = [ratio, selection]; }; - $scope.$watch('currSelection', function (newVal) { - if (typeof(newVal) === 'undefined') { return; } + $scope.$watch('selectedCrop', function (newVal) { + if (angular.isUndefined(newVal)) { return; } var scale = $scope.crop_image_width / $scope.image.width; var selection = newVal[1]; @@ -80,38 +93,83 @@ angular.module('bulbsCmsApp') ]); }); - $scope.computeRatioStyles = function (image, selections) { + $scope.setThumbStyles = function (image, selections) { $scope.ratio_styles = $scope.ratio_styles || {}; - var scale = $scope.thumb_width / image.width; for (var s in selections) { - var top, right, bottom, left; + $scope.computeThumbStyle(image, s, selections[s]); + } + }; - top = $scope.scaleNumber(selections[s].y0, scale); - left = $scope.scaleNumber(selections[s].x0, scale); - right = $scope.scaleNumber(image.width - selections[s].x1, scale); - bottom = $scope.scaleNumber(image.height - selections[s].y1, scale); + $scope.computeThumbStyle = function (image, ratio, selection) { + var top, right, bottom, left; + var scale = $scope.thumb_width / image.width; - var margin = '-'+top+'px -'+right+'px -'+bottom+'px -'+left+'px'; + top = $scope.scaleNumber(selection.y0, scale); + left = $scope.scaleNumber(selection.x0, scale); + right = $scope.scaleNumber(image.width - selection.x1, scale); + bottom = $scope.scaleNumber(image.height - selection.y1, scale); - $scope.ratio_styles[s] = { - margin: margin - }; - } + var margin = '-'+top+'px -'+right+'px -'+bottom+'px -'+left+'px'; + + $scope.ratio_styles[ratio] = { + margin: margin + }; }; - $scope.scaleNumber = function (num, by_scale) { - return Math.floor(num * by_scale); + $scope.setCropStyle = function (image) { + var scale = $scope.crop_image_width / image.width; + var transforms = { + '-webkit-transform': 'scale('+scale+')', + '-moz-transform': 'scale('+scale+')', + '-ms-transform': 'scale('+scale+')', + '-o-transform': 'scale('+scale+')', + 'transform': 'scale('+scale+')' + }; + $scope.crop_image_style = transforms; }; - $scope.close = function () { - $modalInstance.close(); + $scope.scaleNumber = function (num, by_scale) { + return Math.floor(num * by_scale); }; $scope.cancel = function () { $modalInstance.dismiss('cancel'); }; + $scope.save = function () { + // Should probably use a save directive here + $scope.processJcropSelection(jcrop_api.tellSelect()); + $bettycropper.update_selection( + $scope.image.id, + $scope.selectedCrop[0], + $scope.image.selections[$scope.selectedCrop[0]] + ).success(function (data) { + }); + }; + + $scope.saveAndNext = function () { + $scope.processJcropSelection(jcrop_api.tellSelect()); + $bettycropper.update_selection( + $scope.image.id, + $scope.selectedCrop[0], + $scope.image.selections[$scope.selectedCrop[0]] + ).success(function (data) { + var next = ratioOrder.indexOf($scope.selectedCrop[0]) + 1; + if (next >= ratioOrder.length) { + next = 0; + } + $scope.selectedCrop = [ + ratioOrder[next], + $scope.image.selections[ratioOrder[next]] + ]; + }); + + }; + + $bettycropper.detail(id) + .success(setupCropperCallback); + }; $modal.open({ @@ -128,5 +186,4 @@ angular.module('bulbsCmsApp') } }; - }); - + }) diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html index f5b56c264..8f47c2370 100644 --- a/app/views/image-crop-modal.html +++ b/app/views/image-crop-modal.html @@ -5,18 +5,18 @@ From f1a532521be016b9631ff7072a2c2f78041968b4 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Mon, 28 Apr 2014 10:47:45 -0500 Subject: [PATCH 04/27] saving these --- app/scripts/services/imagecropmodal.js | 3 ++- app/views/image-crop-modal.html | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index 03e72ed3d..617ecf522 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -20,12 +20,13 @@ angular.module('bulbsCmsApp') var jcrop_api, ratioOrder; $scope.thumb_width = 180; $scope.crop_image_width = 550; + $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); + $scope.thumb_url = $bettycropper.orig_jpg(id, $scope.thumb_width); var setupCropperCallback = function (data) { $scope.image = data; // $scope.setCropStyle($scope.image); $scope.setThumbStyles($scope.image, $scope.image.selections); - $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); ratioOrder = Object.keys($scope.image.selections); $('#crop-image').Jcrop({ diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html index 8f47c2370..5a4120033 100644 --- a/app/views/image-crop-modal.html +++ b/app/views/image-crop-modal.html @@ -10,7 +10,7 @@
  • - +
From ba33da7fc333953798e506d8bdbe26a31d90f978 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Mon, 28 Apr 2014 11:47:53 -0500 Subject: [PATCH 05/27] thumbnail stuff, finally --- app/scripts/services/imagecropmodal.js | 52 ++++++++++++-------------- app/views/image-crop-modal.html | 3 +- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index 617ecf522..f67f44a7c 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -18,14 +18,12 @@ angular.module('bulbsCmsApp') link: function (scope, element, attrs) { var ModalInstanceCtrl = function ($scope, $interpolate, $bettycropper, $modalInstance, id) { var jcrop_api, ratioOrder; - $scope.thumb_width = 180; + $scope.thumb = {height:180, width: 180}; $scope.crop_image_width = 550; $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); - $scope.thumb_url = $bettycropper.orig_jpg(id, $scope.thumb_width); var setupCropperCallback = function (data) { $scope.image = data; - // $scope.setCropStyle($scope.image); $scope.setThumbStyles($scope.image, $scope.image.selections); ratioOrder = Object.keys($scope.image.selections); @@ -95,7 +93,7 @@ angular.module('bulbsCmsApp') }); $scope.setThumbStyles = function (image, selections) { - $scope.ratio_styles = $scope.ratio_styles || {}; + $scope.thumb_styles = $scope.thumb_styles || {}; for (var s in selections) { $scope.computeThumbStyle(image, s, selections[s]); @@ -103,31 +101,29 @@ angular.module('bulbsCmsApp') }; $scope.computeThumbStyle = function (image, ratio, selection) { - var top, right, bottom, left; - var scale = $scope.thumb_width / image.width; - - top = $scope.scaleNumber(selection.y0, scale); - left = $scope.scaleNumber(selection.x0, scale); - right = $scope.scaleNumber(image.width - selection.x1, scale); - bottom = $scope.scaleNumber(image.height - selection.y1, scale); - - var margin = '-'+top+'px -'+right+'px -'+bottom+'px -'+left+'px'; - - $scope.ratio_styles[ratio] = { - margin: margin - }; - }; + var scale, styles, h_or_w, selection_length, + s_width = selection.x1 - selection.x0, + s_height = selection.y1 - selection.y0; + if (s_width < s_height) { + h_or_w = 'height'; + selection_length = s_height; + } else { + h_or_w = 'width'; + selection_length = s_width; + } - $scope.setCropStyle = function (image) { - var scale = $scope.crop_image_width / image.width; - var transforms = { - '-webkit-transform': 'scale('+scale+')', - '-moz-transform': 'scale('+scale+')', - '-ms-transform': 'scale('+scale+')', - '-o-transform': 'scale('+scale+')', - 'transform': 'scale('+scale+')' - }; - $scope.crop_image_style = transforms; + styles = {}; + scale = $scope.thumb[h_or_w] / selection_length; + styles['background'] = 'url('+$scope.image_url+')'; + styles['background-size'] = $scope.scaleNumber($scope.image.width, scale) + 'px'; + styles['background-position'] = '' + + '-' + $scope.scaleNumber(selection.x0, scale) +'px ' + + '-' + $scope.scaleNumber(selection.y0, scale) + 'px'; + styles['background-repeat'] = 'no-repeat'; + styles['height'] = $scope.scaleNumber(s_height, scale) + 'px'; + styles['width'] = $scope.scaleNumber(s_width, scale) + 'px'; + + $scope.thumb_styles[ratio] = styles; }; $scope.scaleNumber = function (num, by_scale) { diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html index 5a4120033..62cc36f0b 100644 --- a/app/views/image-crop-modal.html +++ b/app/views/image-crop-modal.html @@ -9,8 +9,7 @@
  • -
    - +
From b6efe666557a1f9b02e68475eae4ee11f6830e5c Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Mon, 28 Apr 2014 18:58:20 -0500 Subject: [PATCH 06/27] sum more shit --- app/scripts/services/imagecropmodal.js | 45 ++++++++++++++++---------- app/views/image-crop-modal.html | 20 +++++++----- 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index f67f44a7c..23d3d5571 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -16,17 +16,15 @@ angular.module('bulbsCmsApp') imageId: "=" }, link: function (scope, element, attrs) { - var ModalInstanceCtrl = function ($scope, $interpolate, $bettycropper, $modalInstance, id) { - var jcrop_api, ratioOrder; + var ModalInstanceCtrl = function ($scope, $timeout, $bettycropper, $modalInstance, id) { + var jcrop_api; + $scope.cropMode = false; $scope.thumb = {height:180, width: 180}; $scope.crop_image_width = 550; $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); + $scope.preview_style = {}; - var setupCropperCallback = function (data) { - $scope.image = data; - $scope.setThumbStyles($scope.image, $scope.image.selections); - ratioOrder = Object.keys($scope.image.selections); - + var setupCropper = function () { $('#crop-image').Jcrop({ allowSelect: false, allowMove: true, @@ -35,8 +33,8 @@ angular.module('bulbsCmsApp') }, function () { // Jcrop Init Callback jcrop_api = this; $scope.selectedCrop = [ - ratioOrder[0], - $scope.image.selections[ratioOrder[0]] + $scope.ratioOrder[0], + $scope.image.selections[$scope.ratioOrder[0]] ]; }); }; @@ -70,12 +68,21 @@ angular.module('bulbsCmsApp') // Don't understand why I can't do selectedCrop = {ratio: selection} // in the ng-click handler... $scope.setSelectedCrop = function (ratio, selection) { - $scope.selectedCrop = [ratio, selection]; + $scope.cropMode = true; + if (angular.isUndefined(jcrop_api)) { + $timeout(setupCropper, 0).then(function () { // WHY DO I NEED A TIMEOUT + $scope.selectedCrop = [ratio, selection]; + }); + } else { + $scope.selectedCrop = [ratio, selection]; + } }; $scope.$watch('selectedCrop', function (newVal) { if (angular.isUndefined(newVal)) { return; } + $scope.preview_style = $scope.thumb_styles[$scope.selectedCrop[0]]; + var scale = $scope.crop_image_width / $scope.image.width; var selection = newVal[1]; var ratioNums = newVal[0].split('x'); @@ -95,8 +102,8 @@ angular.module('bulbsCmsApp') $scope.setThumbStyles = function (image, selections) { $scope.thumb_styles = $scope.thumb_styles || {}; - for (var s in selections) { - $scope.computeThumbStyle(image, s, selections[s]); + for (var ratio in selections) { + $scope.computeThumbStyle(image, ratio, selections[ratio]); } }; @@ -152,20 +159,24 @@ angular.module('bulbsCmsApp') $scope.selectedCrop[0], $scope.image.selections[$scope.selectedCrop[0]] ).success(function (data) { - var next = ratioOrder.indexOf($scope.selectedCrop[0]) + 1; - if (next >= ratioOrder.length) { + var next = $scope.ratioOrder.indexOf($scope.selectedCrop[0]) + 1; + if (next >= $scope.ratioOrder.length) { next = 0; } $scope.selectedCrop = [ - ratioOrder[next], - $scope.image.selections[ratioOrder[next]] + $scope.ratioOrder[next], + $scope.image.selections[$scope.ratioOrder[next]] ]; }); }; $bettycropper.detail(id) - .success(setupCropperCallback); + .success(function (data) { + $scope.image = data; + $scope.setThumbStyles($scope.image, $scope.image.selections); + $scope.ratioOrder = Object.keys($scope.image.selections); + }); }; diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html index 62cc36f0b..0951e8fdb 100644 --- a/app/views/image-crop-modal.html +++ b/app/views/image-crop-modal.html @@ -4,18 +4,22 @@ - From 0a4205987e3f2edd4e8c5ea1c866e05028ba4bb6 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Tue, 29 Apr 2014 10:16:01 -0500 Subject: [PATCH 07/27] oh yeeaaaah --- app/scripts/services/imagecropmodal.js | 53 +++++++++++++++++++------- app/views/image-crop-modal.html | 32 +++++++++++----- 2 files changed, 63 insertions(+), 22 deletions(-) diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index 23d3d5571..e1410e40f 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -20,6 +20,8 @@ angular.module('bulbsCmsApp') var jcrop_api; $scope.cropMode = false; $scope.thumb = {height:180, width: 180}; + $scope.preview_thumb = {height: 110, width: 110}; + $scope.crop_image_width = 550; $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); $scope.preview_style = {}; @@ -33,8 +35,8 @@ angular.module('bulbsCmsApp') }, function () { // Jcrop Init Callback jcrop_api = this; $scope.selectedCrop = [ - $scope.ratioOrder[0], - $scope.image.selections[$scope.ratioOrder[0]] + $scope.ratioOrder[$scope.currentCrop], + $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] ]; }); }; @@ -57,16 +59,21 @@ angular.module('bulbsCmsApp') selection.y1 = $scope.scaleNumber(s.y2, 1 / scale); $scope.image.selections[$scope.selectedCrop[0]] = selection; - $scope.computeThumbStyle( + $scope.thumb_styles[$scope.selectedCrop[0]] = $scope.computeThumbStyle( + $scope.image, + $scope.thumb, + $scope.selectedCrop[0], + selection + ); + $scope.preview_style = $scope.computeThumbStyle( $scope.image, + $scope.preview_thumb, $scope.selectedCrop[0], selection ); } }; - // Don't understand why I can't do selectedCrop = {ratio: selection} - // in the ng-click handler... $scope.setSelectedCrop = function (ratio, selection) { $scope.cropMode = true; if (angular.isUndefined(jcrop_api)) { @@ -81,7 +88,12 @@ angular.module('bulbsCmsApp') $scope.$watch('selectedCrop', function (newVal) { if (angular.isUndefined(newVal)) { return; } - $scope.preview_style = $scope.thumb_styles[$scope.selectedCrop[0]]; + $scope.preview_style = $scope.computeThumbStyle( + $scope.image, + $scope.preview_thumb, + newVal[0], + newVal[1] + ); var scale = $scope.crop_image_width / $scope.image.width; var selection = newVal[1]; @@ -103,11 +115,13 @@ angular.module('bulbsCmsApp') $scope.thumb_styles = $scope.thumb_styles || {}; for (var ratio in selections) { - $scope.computeThumbStyle(image, ratio, selections[ratio]); + $scope.thumb_styles[ratio] = $scope.computeThumbStyle( + image, $scope.thumb, ratio, selections[ratio] + ); } }; - $scope.computeThumbStyle = function (image, ratio, selection) { + $scope.computeThumbStyle = function (image, thumb, ratio, selection) { var scale, styles, h_or_w, selection_length, s_width = selection.x1 - selection.x0, s_height = selection.y1 - selection.y0; @@ -120,7 +134,7 @@ angular.module('bulbsCmsApp') } styles = {}; - scale = $scope.thumb[h_or_w] / selection_length; + scale = thumb[h_or_w] / selection_length; styles['background'] = 'url('+$scope.image_url+')'; styles['background-size'] = $scope.scaleNumber($scope.image.width, scale) + 'px'; styles['background-position'] = '' + @@ -129,8 +143,10 @@ angular.module('bulbsCmsApp') styles['background-repeat'] = 'no-repeat'; styles['height'] = $scope.scaleNumber(s_height, scale) + 'px'; styles['width'] = $scope.scaleNumber(s_width, scale) + 'px'; + styles['top'] = '50%'; + styles['margin-top'] = '-' + ($scope.scaleNumber(s_height, scale) / 2) + 'px'; - $scope.thumb_styles[ratio] = styles; + return styles; }; $scope.scaleNumber = function (num, by_scale) { @@ -141,6 +157,10 @@ angular.module('bulbsCmsApp') $modalInstance.dismiss('cancel'); }; + $scope.back = function () { + $scope.cropMode = false; + } + $scope.save = function () { // Should probably use a save directive here $scope.processJcropSelection(jcrop_api.tellSelect()); @@ -159,16 +179,22 @@ angular.module('bulbsCmsApp') $scope.selectedCrop[0], $scope.image.selections[$scope.selectedCrop[0]] ).success(function (data) { - var next = $scope.ratioOrder.indexOf($scope.selectedCrop[0]) + 1; + var next = $scope.currentCrop + 1; if (next >= $scope.ratioOrder.length) { next = 0; } + $scope.currentCrop = next; $scope.selectedCrop = [ - $scope.ratioOrder[next], - $scope.image.selections[$scope.ratioOrder[next]] + $scope.ratioOrder[$scope.currentCrop], + $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] ]; }); + }; + $scope.isCurrentCrop = function (ratio) { + if ($scope.ratioOrder[$scope.currentCrop] === ratio) { + return {color: '#5bc0de'}; + } }; $bettycropper.detail(id) @@ -176,6 +202,7 @@ angular.module('bulbsCmsApp') $scope.image = data; $scope.setThumbStyles($scope.image, $scope.image.selections); $scope.ratioOrder = Object.keys($scope.image.selections); + $scope.currentCrop = 0; }); }; diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html index 0951e8fdb..b82ab71fc 100644 --- a/app/views/image-crop-modal.html +++ b/app/views/image-crop-modal.html @@ -4,21 +4,35 @@ \ No newline at end of file From f6ac80eb579bdfaf2c7e396b67a08c690fcbb123 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Tue, 29 Apr 2014 16:41:41 -0500 Subject: [PATCH 09/27] done --- app/scripts/directives/titleimage.js | 28 +- app/scripts/libraries/editor-cms-bridge.js | 26 +- app/scripts/services/imagecropmodal.js | 379 ++++++++++----------- app/views/image-crop-modal.html | 2 +- 4 files changed, 202 insertions(+), 233 deletions(-) diff --git a/app/scripts/directives/titleimage.js b/app/scripts/directives/titleimage.js index c8f3bef7a..356ab8527 100644 --- a/app/scripts/directives/titleimage.js +++ b/app/scripts/directives/titleimage.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('bulbsCmsApp') - .directive('titleimage', function ($http, $window, $, routes) { + .directive('titleimage', function ($http, $window, $, routes, openImageCropModal) { return { restrict: 'E', templateUrl: routes.PARTIALS_URL + 'titleimage.html', @@ -42,30 +42,8 @@ angular.module('bulbsCmsApp') }); }, scope.editTitleImage = function () { - $window.openImageDrawer( - scope.image.id, - function (data) { - function removeLoadingGif() { - $element.find('.image img[src=\"' + routes.LOADING_IMG_SRC + '\"]').remove(); - } - - removeLoadingGif(); - - if ($element.find('.image').data('imageId') === data.id) { - return; - } - - $element.find('.image img').on('load', removeLoadingGif); - $element.find('.image img').after(''); - - scope.image.id = data.id.toString(); - scope.$apply(); - $window.picturefill(); - if ($element.find('.image img')[0].complete) { removeLoadingGif(); } - }, - function () { return; }, - function (oldImage) { - scope.image = oldImage; + openImageCropModal(scope.image.id).then( + function () { $window.picturefill(); } ); diff --git a/app/scripts/libraries/editor-cms-bridge.js b/app/scripts/libraries/editor-cms-bridge.js index 10a049724..dbb2c6f4f 100644 --- a/app/scripts/libraries/editor-cms-bridge.js +++ b/app/scripts/libraries/editor-cms-bridge.js @@ -75,7 +75,13 @@ This bridges the embed module that the editor exposes & our custom image impleme function editImage(options) { current_id = options.element.getAttribute("data-image-id"); - openImageDrawer(current_id, onDrawerImageChange, onDrawerSave, onDrawerCancel); + + openImageCropModal(current_id).then( + function () { + $(options.element).attr("data-image-id", current_id); + window.picturefill(); + } + ); function onDrawerImageChange(id) { $(options.element).attr("data-image-id", id); @@ -104,7 +110,7 @@ This bridges the embed module that the editor exposes & our custom image impleme editor.on("init", cleanup); function cleanup() { - // hack alert: let's transform old embeds here. Not ideal, but whatever. + // hack alert: let's transform old embeds here. Not ideal, but whatever. var old_embeds = $("[data-type=embed] iframe[src^='/videos/embed']").parents("div.embed"); for (var i = 0; i < old_embeds.length; i++) { var id = $("iframe", old_embeds[i]).attr("src").split("=")[1] @@ -189,7 +195,7 @@ This bridges the embed module that the editor exposes & our custom image impleme function edit(opts) { //populate modal contents - + $("#embed-modal .embed-body").val(unescape($(opts.element).attr("data-body"))); $("#embed-modal .embed-source").val($(opts.element).attr("data-source")); $("#embed-modal .embed-caption").val($(".caption", opts.element).text()); @@ -203,9 +209,9 @@ This bridges the embed module that the editor exposes & our custom image impleme } else { $(".embed-error").hide(); - opts.onChange(opts.element, + opts.onChange(opts.element, {body: embed_body, - caption: $("#embed-modal .embed-caption").val(), + caption: $("#embed-modal .embed-caption").val(), source: $("#embed-modal .embed-source").val(), escapedbody: escape(embed_body) }) @@ -228,12 +234,12 @@ This bridges the embed module that the editor exposes & our custom image impleme } else { $(".embed-error").hide(); - opts.onSuccess(opts.block, - {body: embed_body, - caption: $("#embed-modal .embed-caption").val(), + opts.onSuccess(opts.block, + {body: embed_body, + caption: $("#embed-modal .embed-caption").val(), source: $("#embed-modal .embed-source").val(), escapedbody: escape(embed_body) - }) + }) $("#embed-modal").modal("hide"); } }); @@ -275,4 +281,4 @@ $(document).unbind('keydown').bind('keydown', function (event) { if (doPrevent) { event.preventDefault(); } -}); \ No newline at end of file +}); diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index e1410e40f..f9236199b 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -1,224 +1,209 @@ 'use strict'; angular.module('bulbsCmsApp') - .factory('openImageCropModal', function ($document, $compile, $rootScope) { - return function (id) { - var el = $compile( - "" - )($rootScope); - $document.find('body').append(el); - }; - }) - .directive('ngImageCropModal', function ($modal, routes) { - return { - restrict: 'E', - scope: { - imageId: "=" - }, - link: function (scope, element, attrs) { - var ModalInstanceCtrl = function ($scope, $timeout, $bettycropper, $modalInstance, id) { - var jcrop_api; - $scope.cropMode = false; - $scope.thumb = {height:180, width: 180}; - $scope.preview_thumb = {height: 110, width: 110}; - - $scope.crop_image_width = 550; - $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); - $scope.preview_style = {}; - - var setupCropper = function () { - $('#crop-image').Jcrop({ - allowSelect: false, - allowMove: true, - allowResize: true, - keySupport: false - }, function () { // Jcrop Init Callback - jcrop_api = this; - $scope.selectedCrop = [ - $scope.ratioOrder[$scope.currentCrop], - $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] - ]; - }); - }; - - $scope.processJcropSelection = function (s) { - if ( - angular.isNumber(s.x) && !isNaN(s.x) || - angular.isNumber(s.y) && !isNaN(s.y) || - angular.isNumber(s.x2) && !isNaN(s.x2) || - angular.isNumber(s.y2) && !isNaN(s.y2) || - angular.isNumber(s.w) && !isNaN(s.w) || - angular.isNumber(s.h) && !isNaN(s.h) - ) { - var selection = {}; - - var scale = $scope.crop_image_width / $scope.image.width; - selection.x0 = $scope.scaleNumber(s.x, 1 / scale); - selection.y0 = $scope.scaleNumber(s.y, 1 / scale); - selection.x1 = $scope.scaleNumber(s.x2, 1 / scale); - selection.y1 = $scope.scaleNumber(s.y2, 1 / scale); - - $scope.image.selections[$scope.selectedCrop[0]] = selection; - $scope.thumb_styles[$scope.selectedCrop[0]] = $scope.computeThumbStyle( - $scope.image, - $scope.thumb, - $scope.selectedCrop[0], - selection - ); - $scope.preview_style = $scope.computeThumbStyle( - $scope.image, - $scope.preview_thumb, - $scope.selectedCrop[0], - selection - ); - } - }; - - $scope.setSelectedCrop = function (ratio, selection) { - $scope.cropMode = true; - if (angular.isUndefined(jcrop_api)) { - $timeout(setupCropper, 0).then(function () { // WHY DO I NEED A TIMEOUT - $scope.selectedCrop = [ratio, selection]; - }); - } else { - $scope.selectedCrop = [ratio, selection]; - } - }; + .factory('openImageCropModal', function ($window, $document, $compile, $rootScope, $modal, routes) { + var openImageCropModal = function (id) { + var ModalInstanceCtrl = function ($scope, $timeout, $bettycropper, $modalInstance, id) { + var jcrop_api; + $scope.cropMode = false; + $scope.thumb = {height:180, width: 180}; + $scope.preview_thumb = {height: 110, width: 110}; + + $scope.crop_image_width = 550; + $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); + $scope.preview_style = {}; + + var setupCropper = function () { + $('#crop-image').Jcrop({ + allowSelect: false, + allowMove: true, + allowResize: true, + keySupport: false + }, function () { // Jcrop Init Callback + jcrop_api = this; + $scope.selectedCrop = [ + $scope.ratioOrder[$scope.currentCrop], + $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] + ]; + }); + }; + + $scope.processJcropSelection = function (s) { + if ( + angular.isNumber(s.x) && !isNaN(s.x) || + angular.isNumber(s.y) && !isNaN(s.y) || + angular.isNumber(s.x2) && !isNaN(s.x2) || + angular.isNumber(s.y2) && !isNaN(s.y2) || + angular.isNumber(s.w) && !isNaN(s.w) || + angular.isNumber(s.h) && !isNaN(s.h) + ) { + var selection = {}; - $scope.$watch('selectedCrop', function (newVal) { - if (angular.isUndefined(newVal)) { return; } + var scale = $scope.crop_image_width / $scope.image.width; + selection.x0 = $scope.scaleNumber(s.x, 1 / scale); + selection.y0 = $scope.scaleNumber(s.y, 1 / scale); + selection.x1 = $scope.scaleNumber(s.x2, 1 / scale); + selection.y1 = $scope.scaleNumber(s.y2, 1 / scale); + $scope.image.selections[$scope.selectedCrop[0]] = selection; + $scope.thumb_styles[$scope.selectedCrop[0]] = $scope.computeThumbStyle( + $scope.image, + $scope.thumb, + $scope.selectedCrop[0], + selection + ); $scope.preview_style = $scope.computeThumbStyle( $scope.image, $scope.preview_thumb, - newVal[0], - newVal[1] + $scope.selectedCrop[0], + selection ); + } + }; - var scale = $scope.crop_image_width / $scope.image.width; - var selection = newVal[1]; - var ratioNums = newVal[0].split('x'); - - jcrop_api.setOptions({ - aspectRatio: ratioNums[0] / ratioNums[1] + $scope.setSelectedCrop = function (ratio, selection) { + $scope.cropMode = true; + if (angular.isUndefined(jcrop_api)) { + $timeout(setupCropper, 0).then(function () { // WHY DO I NEED A TIMEOUT + $scope.selectedCrop = [ratio, selection]; }); + } else { + $scope.selectedCrop = [ratio, selection]; + } + }; + + $scope.$watch('selectedCrop', function (newVal) { + if (angular.isUndefined(newVal)) { return; } - jcrop_api.setSelect([ - $scope.scaleNumber(selection.x0, scale), - $scope.scaleNumber(selection.y0, scale), - $scope.scaleNumber(selection.x1, scale), - $scope.scaleNumber(selection.y1, scale) - ]); + $scope.preview_style = $scope.computeThumbStyle( + $scope.image, + $scope.preview_thumb, + newVal[0], + newVal[1] + ); + + var scale = $scope.crop_image_width / $scope.image.width; + var selection = newVal[1]; + var ratioNums = newVal[0].split('x'); + + jcrop_api.setOptions({ + aspectRatio: ratioNums[0] / ratioNums[1] }); - $scope.setThumbStyles = function (image, selections) { - $scope.thumb_styles = $scope.thumb_styles || {}; + jcrop_api.setSelect([ + $scope.scaleNumber(selection.x0, scale), + $scope.scaleNumber(selection.y0, scale), + $scope.scaleNumber(selection.x1, scale), + $scope.scaleNumber(selection.y1, scale) + ]); + }); - for (var ratio in selections) { - $scope.thumb_styles[ratio] = $scope.computeThumbStyle( - image, $scope.thumb, ratio, selections[ratio] - ); - } - }; - - $scope.computeThumbStyle = function (image, thumb, ratio, selection) { - var scale, styles, h_or_w, selection_length, - s_width = selection.x1 - selection.x0, - s_height = selection.y1 - selection.y0; - if (s_width < s_height) { - h_or_w = 'height'; - selection_length = s_height; - } else { - h_or_w = 'width'; - selection_length = s_width; - } + $scope.setThumbStyles = function (image, selections) { + $scope.thumb_styles = $scope.thumb_styles || {}; - styles = {}; - scale = thumb[h_or_w] / selection_length; - styles['background'] = 'url('+$scope.image_url+')'; - styles['background-size'] = $scope.scaleNumber($scope.image.width, scale) + 'px'; - styles['background-position'] = '' + - '-' + $scope.scaleNumber(selection.x0, scale) +'px ' + - '-' + $scope.scaleNumber(selection.y0, scale) + 'px'; - styles['background-repeat'] = 'no-repeat'; - styles['height'] = $scope.scaleNumber(s_height, scale) + 'px'; - styles['width'] = $scope.scaleNumber(s_width, scale) + 'px'; - styles['top'] = '50%'; - styles['margin-top'] = '-' + ($scope.scaleNumber(s_height, scale) / 2) + 'px'; - - return styles; - }; - - $scope.scaleNumber = function (num, by_scale) { - return Math.floor(num * by_scale); - }; - - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - - $scope.back = function () { - $scope.cropMode = false; + for (var ratio in selections) { + $scope.thumb_styles[ratio] = $scope.computeThumbStyle( + image, $scope.thumb, ratio, selections[ratio] + ); } + }; - $scope.save = function () { - // Should probably use a save directive here - $scope.processJcropSelection(jcrop_api.tellSelect()); - $bettycropper.update_selection( - $scope.image.id, - $scope.selectedCrop[0], - $scope.image.selections[$scope.selectedCrop[0]] - ).success(function (data) { - }); - }; + $scope.computeThumbStyle = function (image, thumb, ratio, selection) { + var scale, styles, h_or_w, selection_length, + s_width = selection.x1 - selection.x0, + s_height = selection.y1 - selection.y0; + if (s_width < s_height) { + h_or_w = 'height'; + selection_length = s_height; + } else { + h_or_w = 'width'; + selection_length = s_width; + } - $scope.saveAndNext = function () { - $scope.processJcropSelection(jcrop_api.tellSelect()); - $bettycropper.update_selection( - $scope.image.id, - $scope.selectedCrop[0], - $scope.image.selections[$scope.selectedCrop[0]] - ).success(function (data) { - var next = $scope.currentCrop + 1; - if (next >= $scope.ratioOrder.length) { - next = 0; - } - $scope.currentCrop = next; - $scope.selectedCrop = [ - $scope.ratioOrder[$scope.currentCrop], - $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] - ]; - }); - }; + styles = {}; + scale = thumb[h_or_w] / selection_length; + styles['background'] = 'url('+$scope.image_url+')'; + styles['background-size'] = $scope.scaleNumber($scope.image.width, scale) + 'px'; + styles['background-position'] = '' + + '-' + $scope.scaleNumber(selection.x0, scale) +'px ' + + '-' + $scope.scaleNumber(selection.y0, scale) + 'px'; + styles['background-repeat'] = 'no-repeat'; + styles['height'] = $scope.scaleNumber(s_height, scale) + 'px'; + styles['width'] = $scope.scaleNumber(s_width, scale) + 'px'; + styles['top'] = '50%'; + styles['margin-top'] = '-' + ($scope.scaleNumber(s_height, scale) / 2) + 'px'; + + return styles; + }; - $scope.isCurrentCrop = function (ratio) { - if ($scope.ratioOrder[$scope.currentCrop] === ratio) { - return {color: '#5bc0de'}; - } - }; - - $bettycropper.detail(id) - .success(function (data) { - $scope.image = data; - $scope.setThumbStyles($scope.image, $scope.image.selections); - $scope.ratioOrder = Object.keys($scope.image.selections); - $scope.currentCrop = 0; - }); + $scope.scaleNumber = function (num, by_scale) { + return Math.floor(num * by_scale); + }; + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); }; - $modal.open({ - templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", - controller: ModalInstanceCtrl, - resolve: { - id: function () { return scope.imageId; } + $scope.back = function () { + $scope.cropMode = false; + } + + $scope.saveAndQuit = function () { + // Should probably use a save directive here + $scope.processJcropSelection(jcrop_api.tellSelect()); + $bettycropper.update_selection( + $scope.image.id, + $scope.selectedCrop[0], + $scope.image.selections[$scope.selectedCrop[0]] + ).success(function (data) { + $modalInstance.close(); // Should be passing updated styling here + }); + }; + + $scope.saveAndNext = function () { + $scope.processJcropSelection(jcrop_api.tellSelect()); + $bettycropper.update_selection( + $scope.image.id, + $scope.selectedCrop[0], + $scope.image.selections[$scope.selectedCrop[0]] + ).success(function (data) { + var next = $scope.currentCrop + 1; + if (next >= $scope.ratioOrder.length) { + next = 0; + } + $scope.currentCrop = next; + $scope.selectedCrop = [ + $scope.ratioOrder[$scope.currentCrop], + $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] + ]; + }); + }; + + $scope.isCurrentCrop = function (ratio) { + if ($scope.ratioOrder[$scope.currentCrop] === ratio) { + return {color: '#5bc0de'}; } - }) - .result - .finally(function () { - element.remove(); - }) + }; + + $bettycropper.detail(id) + .success(function (data) { + $scope.image = data; + $scope.setThumbStyles($scope.image, $scope.image.selections); + $scope.ratioOrder = Object.keys($scope.image.selections); + $scope.currentCrop = 0; + }); + + }; + + return $modal.open({ + templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", + controller: ModalInstanceCtrl, + resolve: { + id: function () { return id; } + } + }).result; - } }; + $window.openImageCropModal = openImageCropModal; // THIS IS SOME BULLSHIT + return openImageCropModal; }) diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html index b82ab71fc..3a23ebb4e 100644 --- a/app/views/image-crop-modal.html +++ b/app/views/image-crop-modal.html @@ -15,7 +15,7 @@
- +
From 34d2ab0b91d4b21a770357554ac54d430779cf21 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Tue, 22 Apr 2014 16:25:34 -0500 Subject: [PATCH 10/27] adding bettycropper service and imagecropmodal --- app/scripts/app.js | 2 +- app/scripts/modules/betty-cropper.js | 63 ++++++++++++++++++++++++++ app/scripts/services/imagecropmodal.js | 25 ++++++++++ app/views/image-crop-modal.html | 1 + 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 app/scripts/modules/betty-cropper.js create mode 100644 app/scripts/services/imagecropmodal.js create mode 100644 app/views/image-crop-modal.html diff --git a/app/scripts/app.js b/app/scripts/app.js index 96fae2fa5..31b71f81b 100644 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -16,9 +16,9 @@ angular.module('bulbsCmsApp', [ 'ngResource', 'ngSanitize', 'ngRoute', - 'restangular', 'ui.bootstrap', 'ui.bootstrap.datetimepicker', + 'bettyCropper', 'jquery', 'underscore', 'NProgress', diff --git a/app/scripts/modules/betty-cropper.js b/app/scripts/modules/betty-cropper.js new file mode 100644 index 000000000..76411b517 --- /dev/null +++ b/app/scripts/modules/betty-cropper.js @@ -0,0 +1,63 @@ +angular.module('bettyCropper', []) + .service('$bettycropper', function $bettycropper($http, IMAGE_SERVER_URL) { + this.detail = function (id) { + return $http({ + method: 'GET', + url: IMAGE_SERVER_URL + '/api/' + id, + headers: { + 'X-Betty-Api-Key': BC_API_KEY, + 'Content-Type': undefined + }, + transformRequest: angular.identity + }); + }; + + this.detail_patch = function (id, name, credit, selections) { + return $http({ + method: 'GET', + url: IMAGE_SERVER_URL + '/api/' + id, + headers: { + 'X-Betty-Api-Key': BC_API_KEY, + 'Content-Type': undefined + }, + data: { + name: name, + credit: credit, + selections: selections + }, + transformRequest: angular.identity + }); + }; + + this.new = function (image, name, credit) { + var imageData = new FormData(); + imageData.append('image', image); + if (name) { imageData.append('name', name); } + if (credit) { imageData.append('credit', credit); } + + return $http({ + method: 'POST', + url: IMAGE_SERVER_URL + '/api/new', + headers: { + 'X-Betty-Api-Key': BC_API_KEY, + 'Content-Type': undefined + }, + data: imageData, + transformRequest: angular.identity + }); + }; + + this.update_selection = function (id, ratio, selections) { + return $http({ + method: 'POST', + url: IMAGE_SERVER_URL + '/api/' + id + "/" + ratio, + headers: { + 'X-Betty-Api-Key': BC_API_KEY, + 'Content-Type': undefined + }, + data: selections, + transformRequest: angular.identity + }); + }; + + }); diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js new file mode 100644 index 000000000..0fdf041d5 --- /dev/null +++ b/app/scripts/services/imagecropmodal.js @@ -0,0 +1,25 @@ +'use strict'; + +angular.module('bulbsCmsApp') + .factory('openImageCropModal', function ($document, $compile, $rootScope) { + return function () { + var el = $compile("")($rootScope); + $document.find('body').append(el); + }; + }) + .directive('ngImageCropModal', function ($modal, $bettycropper, routes) { + return { + restrict: 'E', + scope: {}, + link: function (scope, element, attrs) { + var ModalInstanceCtrl = function ($scope, $modalInstance) { + + }; + $modal.open({ + templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", + controller: ModalInstanceCtrl + }); + } + }; + }); + diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html new file mode 100644 index 000000000..d531e8e05 --- /dev/null +++ b/app/views/image-crop-modal.html @@ -0,0 +1 @@ + From 4fda87a299adfc8cee927b7687b3b39ea6f4b4c1 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Wed, 23 Apr 2014 18:30:08 -0500 Subject: [PATCH 11/27] adding bettycropper service and image crop modal integration --- app/scripts/modules/betty-cropper.js | 41 ++++- app/scripts/services/imagecropmodal.js | 217 ++++++++++++++++++++++++- app/views/image-crop-modal.html | 40 ++++- 3 files changed, 284 insertions(+), 14 deletions(-) diff --git a/app/scripts/modules/betty-cropper.js b/app/scripts/modules/betty-cropper.js index 76411b517..6cec91738 100644 --- a/app/scripts/modules/betty-cropper.js +++ b/app/scripts/modules/betty-cropper.js @@ -1,5 +1,12 @@ angular.module('bettyCropper', []) - .service('$bettycropper', function $bettycropper($http, IMAGE_SERVER_URL) { + .service('$bettycropper', function $bettycropper($http, $interpolate, IMAGE_SERVER_URL, BC_API_KEY) { + + /*\ + + Betty Cropper API + + \*/ + this.detail = function (id) { return $http({ method: 'GET', @@ -14,7 +21,7 @@ angular.module('bettyCropper', []) this.detail_patch = function (id, name, credit, selections) { return $http({ - method: 'GET', + method: 'PATCH', url: IMAGE_SERVER_URL + '/api/' + id, headers: { 'X-Betty-Api-Key': BC_API_KEY, @@ -55,9 +62,35 @@ angular.module('bettyCropper', []) 'X-Betty-Api-Key': BC_API_KEY, 'Content-Type': undefined }, - data: selections, - transformRequest: angular.identity + data: selections + }); + }; + + /*\ + + Convenience Methods + + \*/ + + this.url = function (id, crop, width, format) { + var exp = $interpolate( + "{{ url }}/{{ id }}/{{ crop }}/{{ width }}.{{ format }}" + ); + return exp({ + url: IMAGE_SERVER_URL, + id: id, + crop: crop, + width: width, + format: format }); }; + this.orig_jpg = function (id, width) { + return this.url(id, 'original', width, 'jpg'); + }; + + this.orig_gif = function (id, width) { + return this.url(id, 'original', width, 'gif'); + }; + }); diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index 0fdf041d5..e1410e40f 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -2,24 +2,223 @@ angular.module('bulbsCmsApp') .factory('openImageCropModal', function ($document, $compile, $rootScope) { - return function () { - var el = $compile("")($rootScope); + return function (id) { + var el = $compile( + "" + )($rootScope); $document.find('body').append(el); }; }) - .directive('ngImageCropModal', function ($modal, $bettycropper, routes) { + .directive('ngImageCropModal', function ($modal, routes) { return { restrict: 'E', - scope: {}, + scope: { + imageId: "=" + }, link: function (scope, element, attrs) { - var ModalInstanceCtrl = function ($scope, $modalInstance) { + var ModalInstanceCtrl = function ($scope, $timeout, $bettycropper, $modalInstance, id) { + var jcrop_api; + $scope.cropMode = false; + $scope.thumb = {height:180, width: 180}; + $scope.preview_thumb = {height: 110, width: 110}; + + $scope.crop_image_width = 550; + $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); + $scope.preview_style = {}; + + var setupCropper = function () { + $('#crop-image').Jcrop({ + allowSelect: false, + allowMove: true, + allowResize: true, + keySupport: false + }, function () { // Jcrop Init Callback + jcrop_api = this; + $scope.selectedCrop = [ + $scope.ratioOrder[$scope.currentCrop], + $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] + ]; + }); + }; + + $scope.processJcropSelection = function (s) { + if ( + angular.isNumber(s.x) && !isNaN(s.x) || + angular.isNumber(s.y) && !isNaN(s.y) || + angular.isNumber(s.x2) && !isNaN(s.x2) || + angular.isNumber(s.y2) && !isNaN(s.y2) || + angular.isNumber(s.w) && !isNaN(s.w) || + angular.isNumber(s.h) && !isNaN(s.h) + ) { + var selection = {}; + + var scale = $scope.crop_image_width / $scope.image.width; + selection.x0 = $scope.scaleNumber(s.x, 1 / scale); + selection.y0 = $scope.scaleNumber(s.y, 1 / scale); + selection.x1 = $scope.scaleNumber(s.x2, 1 / scale); + selection.y1 = $scope.scaleNumber(s.y2, 1 / scale); + + $scope.image.selections[$scope.selectedCrop[0]] = selection; + $scope.thumb_styles[$scope.selectedCrop[0]] = $scope.computeThumbStyle( + $scope.image, + $scope.thumb, + $scope.selectedCrop[0], + selection + ); + $scope.preview_style = $scope.computeThumbStyle( + $scope.image, + $scope.preview_thumb, + $scope.selectedCrop[0], + selection + ); + } + }; + + $scope.setSelectedCrop = function (ratio, selection) { + $scope.cropMode = true; + if (angular.isUndefined(jcrop_api)) { + $timeout(setupCropper, 0).then(function () { // WHY DO I NEED A TIMEOUT + $scope.selectedCrop = [ratio, selection]; + }); + } else { + $scope.selectedCrop = [ratio, selection]; + } + }; + + $scope.$watch('selectedCrop', function (newVal) { + if (angular.isUndefined(newVal)) { return; } + + $scope.preview_style = $scope.computeThumbStyle( + $scope.image, + $scope.preview_thumb, + newVal[0], + newVal[1] + ); + + var scale = $scope.crop_image_width / $scope.image.width; + var selection = newVal[1]; + var ratioNums = newVal[0].split('x'); + + jcrop_api.setOptions({ + aspectRatio: ratioNums[0] / ratioNums[1] + }); + + jcrop_api.setSelect([ + $scope.scaleNumber(selection.x0, scale), + $scope.scaleNumber(selection.y0, scale), + $scope.scaleNumber(selection.x1, scale), + $scope.scaleNumber(selection.y1, scale) + ]); + }); + + $scope.setThumbStyles = function (image, selections) { + $scope.thumb_styles = $scope.thumb_styles || {}; + + for (var ratio in selections) { + $scope.thumb_styles[ratio] = $scope.computeThumbStyle( + image, $scope.thumb, ratio, selections[ratio] + ); + } + }; + + $scope.computeThumbStyle = function (image, thumb, ratio, selection) { + var scale, styles, h_or_w, selection_length, + s_width = selection.x1 - selection.x0, + s_height = selection.y1 - selection.y0; + if (s_width < s_height) { + h_or_w = 'height'; + selection_length = s_height; + } else { + h_or_w = 'width'; + selection_length = s_width; + } + + styles = {}; + scale = thumb[h_or_w] / selection_length; + styles['background'] = 'url('+$scope.image_url+')'; + styles['background-size'] = $scope.scaleNumber($scope.image.width, scale) + 'px'; + styles['background-position'] = '' + + '-' + $scope.scaleNumber(selection.x0, scale) +'px ' + + '-' + $scope.scaleNumber(selection.y0, scale) + 'px'; + styles['background-repeat'] = 'no-repeat'; + styles['height'] = $scope.scaleNumber(s_height, scale) + 'px'; + styles['width'] = $scope.scaleNumber(s_width, scale) + 'px'; + styles['top'] = '50%'; + styles['margin-top'] = '-' + ($scope.scaleNumber(s_height, scale) / 2) + 'px'; + + return styles; + }; + + $scope.scaleNumber = function (num, by_scale) { + return Math.floor(num * by_scale); + }; + + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); + }; + + $scope.back = function () { + $scope.cropMode = false; + } + + $scope.save = function () { + // Should probably use a save directive here + $scope.processJcropSelection(jcrop_api.tellSelect()); + $bettycropper.update_selection( + $scope.image.id, + $scope.selectedCrop[0], + $scope.image.selections[$scope.selectedCrop[0]] + ).success(function (data) { + }); + }; + + $scope.saveAndNext = function () { + $scope.processJcropSelection(jcrop_api.tellSelect()); + $bettycropper.update_selection( + $scope.image.id, + $scope.selectedCrop[0], + $scope.image.selections[$scope.selectedCrop[0]] + ).success(function (data) { + var next = $scope.currentCrop + 1; + if (next >= $scope.ratioOrder.length) { + next = 0; + } + $scope.currentCrop = next; + $scope.selectedCrop = [ + $scope.ratioOrder[$scope.currentCrop], + $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] + ]; + }); + }; + + $scope.isCurrentCrop = function (ratio) { + if ($scope.ratioOrder[$scope.currentCrop] === ratio) { + return {color: '#5bc0de'}; + } + }; + + $bettycropper.detail(id) + .success(function (data) { + $scope.image = data; + $scope.setThumbStyles($scope.image, $scope.image.selections); + $scope.ratioOrder = Object.keys($scope.image.selections); + $scope.currentCrop = 0; + }); }; + $modal.open({ templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", - controller: ModalInstanceCtrl - }); + controller: ModalInstanceCtrl, + resolve: { + id: function () { return scope.imageId; } + } + }) + .result + .finally(function () { + element.remove(); + }) + } }; - }); - + }) diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html index d531e8e05..b82ab71fc 100644 --- a/app/views/image-crop-modal.html +++ b/app/views/image-crop-modal.html @@ -1 +1,39 @@ - +
+ + +
From c68d02a5abb0c6876c9719df8407f701b104063b Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Tue, 29 Apr 2014 16:41:41 -0500 Subject: [PATCH 12/27] done --- app/scripts/directives/titleimage.js | 28 +- app/scripts/libraries/editor-cms-bridge.js | 26 +- app/scripts/services/imagecropmodal.js | 379 ++++++++++----------- app/views/image-crop-modal.html | 2 +- 4 files changed, 202 insertions(+), 233 deletions(-) diff --git a/app/scripts/directives/titleimage.js b/app/scripts/directives/titleimage.js index c8f3bef7a..356ab8527 100644 --- a/app/scripts/directives/titleimage.js +++ b/app/scripts/directives/titleimage.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('bulbsCmsApp') - .directive('titleimage', function ($http, $window, $, routes) { + .directive('titleimage', function ($http, $window, $, routes, openImageCropModal) { return { restrict: 'E', templateUrl: routes.PARTIALS_URL + 'titleimage.html', @@ -42,30 +42,8 @@ angular.module('bulbsCmsApp') }); }, scope.editTitleImage = function () { - $window.openImageDrawer( - scope.image.id, - function (data) { - function removeLoadingGif() { - $element.find('.image img[src=\"' + routes.LOADING_IMG_SRC + '\"]').remove(); - } - - removeLoadingGif(); - - if ($element.find('.image').data('imageId') === data.id) { - return; - } - - $element.find('.image img').on('load', removeLoadingGif); - $element.find('.image img').after(''); - - scope.image.id = data.id.toString(); - scope.$apply(); - $window.picturefill(); - if ($element.find('.image img')[0].complete) { removeLoadingGif(); } - }, - function () { return; }, - function (oldImage) { - scope.image = oldImage; + openImageCropModal(scope.image.id).then( + function () { $window.picturefill(); } ); diff --git a/app/scripts/libraries/editor-cms-bridge.js b/app/scripts/libraries/editor-cms-bridge.js index 10a049724..dbb2c6f4f 100644 --- a/app/scripts/libraries/editor-cms-bridge.js +++ b/app/scripts/libraries/editor-cms-bridge.js @@ -75,7 +75,13 @@ This bridges the embed module that the editor exposes & our custom image impleme function editImage(options) { current_id = options.element.getAttribute("data-image-id"); - openImageDrawer(current_id, onDrawerImageChange, onDrawerSave, onDrawerCancel); + + openImageCropModal(current_id).then( + function () { + $(options.element).attr("data-image-id", current_id); + window.picturefill(); + } + ); function onDrawerImageChange(id) { $(options.element).attr("data-image-id", id); @@ -104,7 +110,7 @@ This bridges the embed module that the editor exposes & our custom image impleme editor.on("init", cleanup); function cleanup() { - // hack alert: let's transform old embeds here. Not ideal, but whatever. + // hack alert: let's transform old embeds here. Not ideal, but whatever. var old_embeds = $("[data-type=embed] iframe[src^='/videos/embed']").parents("div.embed"); for (var i = 0; i < old_embeds.length; i++) { var id = $("iframe", old_embeds[i]).attr("src").split("=")[1] @@ -189,7 +195,7 @@ This bridges the embed module that the editor exposes & our custom image impleme function edit(opts) { //populate modal contents - + $("#embed-modal .embed-body").val(unescape($(opts.element).attr("data-body"))); $("#embed-modal .embed-source").val($(opts.element).attr("data-source")); $("#embed-modal .embed-caption").val($(".caption", opts.element).text()); @@ -203,9 +209,9 @@ This bridges the embed module that the editor exposes & our custom image impleme } else { $(".embed-error").hide(); - opts.onChange(opts.element, + opts.onChange(opts.element, {body: embed_body, - caption: $("#embed-modal .embed-caption").val(), + caption: $("#embed-modal .embed-caption").val(), source: $("#embed-modal .embed-source").val(), escapedbody: escape(embed_body) }) @@ -228,12 +234,12 @@ This bridges the embed module that the editor exposes & our custom image impleme } else { $(".embed-error").hide(); - opts.onSuccess(opts.block, - {body: embed_body, - caption: $("#embed-modal .embed-caption").val(), + opts.onSuccess(opts.block, + {body: embed_body, + caption: $("#embed-modal .embed-caption").val(), source: $("#embed-modal .embed-source").val(), escapedbody: escape(embed_body) - }) + }) $("#embed-modal").modal("hide"); } }); @@ -275,4 +281,4 @@ $(document).unbind('keydown').bind('keydown', function (event) { if (doPrevent) { event.preventDefault(); } -}); \ No newline at end of file +}); diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index e1410e40f..f9236199b 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -1,224 +1,209 @@ 'use strict'; angular.module('bulbsCmsApp') - .factory('openImageCropModal', function ($document, $compile, $rootScope) { - return function (id) { - var el = $compile( - "" - )($rootScope); - $document.find('body').append(el); - }; - }) - .directive('ngImageCropModal', function ($modal, routes) { - return { - restrict: 'E', - scope: { - imageId: "=" - }, - link: function (scope, element, attrs) { - var ModalInstanceCtrl = function ($scope, $timeout, $bettycropper, $modalInstance, id) { - var jcrop_api; - $scope.cropMode = false; - $scope.thumb = {height:180, width: 180}; - $scope.preview_thumb = {height: 110, width: 110}; - - $scope.crop_image_width = 550; - $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); - $scope.preview_style = {}; - - var setupCropper = function () { - $('#crop-image').Jcrop({ - allowSelect: false, - allowMove: true, - allowResize: true, - keySupport: false - }, function () { // Jcrop Init Callback - jcrop_api = this; - $scope.selectedCrop = [ - $scope.ratioOrder[$scope.currentCrop], - $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] - ]; - }); - }; - - $scope.processJcropSelection = function (s) { - if ( - angular.isNumber(s.x) && !isNaN(s.x) || - angular.isNumber(s.y) && !isNaN(s.y) || - angular.isNumber(s.x2) && !isNaN(s.x2) || - angular.isNumber(s.y2) && !isNaN(s.y2) || - angular.isNumber(s.w) && !isNaN(s.w) || - angular.isNumber(s.h) && !isNaN(s.h) - ) { - var selection = {}; - - var scale = $scope.crop_image_width / $scope.image.width; - selection.x0 = $scope.scaleNumber(s.x, 1 / scale); - selection.y0 = $scope.scaleNumber(s.y, 1 / scale); - selection.x1 = $scope.scaleNumber(s.x2, 1 / scale); - selection.y1 = $scope.scaleNumber(s.y2, 1 / scale); - - $scope.image.selections[$scope.selectedCrop[0]] = selection; - $scope.thumb_styles[$scope.selectedCrop[0]] = $scope.computeThumbStyle( - $scope.image, - $scope.thumb, - $scope.selectedCrop[0], - selection - ); - $scope.preview_style = $scope.computeThumbStyle( - $scope.image, - $scope.preview_thumb, - $scope.selectedCrop[0], - selection - ); - } - }; - - $scope.setSelectedCrop = function (ratio, selection) { - $scope.cropMode = true; - if (angular.isUndefined(jcrop_api)) { - $timeout(setupCropper, 0).then(function () { // WHY DO I NEED A TIMEOUT - $scope.selectedCrop = [ratio, selection]; - }); - } else { - $scope.selectedCrop = [ratio, selection]; - } - }; + .factory('openImageCropModal', function ($window, $document, $compile, $rootScope, $modal, routes) { + var openImageCropModal = function (id) { + var ModalInstanceCtrl = function ($scope, $timeout, $bettycropper, $modalInstance, id) { + var jcrop_api; + $scope.cropMode = false; + $scope.thumb = {height:180, width: 180}; + $scope.preview_thumb = {height: 110, width: 110}; + + $scope.crop_image_width = 550; + $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); + $scope.preview_style = {}; + + var setupCropper = function () { + $('#crop-image').Jcrop({ + allowSelect: false, + allowMove: true, + allowResize: true, + keySupport: false + }, function () { // Jcrop Init Callback + jcrop_api = this; + $scope.selectedCrop = [ + $scope.ratioOrder[$scope.currentCrop], + $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] + ]; + }); + }; + + $scope.processJcropSelection = function (s) { + if ( + angular.isNumber(s.x) && !isNaN(s.x) || + angular.isNumber(s.y) && !isNaN(s.y) || + angular.isNumber(s.x2) && !isNaN(s.x2) || + angular.isNumber(s.y2) && !isNaN(s.y2) || + angular.isNumber(s.w) && !isNaN(s.w) || + angular.isNumber(s.h) && !isNaN(s.h) + ) { + var selection = {}; - $scope.$watch('selectedCrop', function (newVal) { - if (angular.isUndefined(newVal)) { return; } + var scale = $scope.crop_image_width / $scope.image.width; + selection.x0 = $scope.scaleNumber(s.x, 1 / scale); + selection.y0 = $scope.scaleNumber(s.y, 1 / scale); + selection.x1 = $scope.scaleNumber(s.x2, 1 / scale); + selection.y1 = $scope.scaleNumber(s.y2, 1 / scale); + $scope.image.selections[$scope.selectedCrop[0]] = selection; + $scope.thumb_styles[$scope.selectedCrop[0]] = $scope.computeThumbStyle( + $scope.image, + $scope.thumb, + $scope.selectedCrop[0], + selection + ); $scope.preview_style = $scope.computeThumbStyle( $scope.image, $scope.preview_thumb, - newVal[0], - newVal[1] + $scope.selectedCrop[0], + selection ); + } + }; - var scale = $scope.crop_image_width / $scope.image.width; - var selection = newVal[1]; - var ratioNums = newVal[0].split('x'); - - jcrop_api.setOptions({ - aspectRatio: ratioNums[0] / ratioNums[1] + $scope.setSelectedCrop = function (ratio, selection) { + $scope.cropMode = true; + if (angular.isUndefined(jcrop_api)) { + $timeout(setupCropper, 0).then(function () { // WHY DO I NEED A TIMEOUT + $scope.selectedCrop = [ratio, selection]; }); + } else { + $scope.selectedCrop = [ratio, selection]; + } + }; + + $scope.$watch('selectedCrop', function (newVal) { + if (angular.isUndefined(newVal)) { return; } - jcrop_api.setSelect([ - $scope.scaleNumber(selection.x0, scale), - $scope.scaleNumber(selection.y0, scale), - $scope.scaleNumber(selection.x1, scale), - $scope.scaleNumber(selection.y1, scale) - ]); + $scope.preview_style = $scope.computeThumbStyle( + $scope.image, + $scope.preview_thumb, + newVal[0], + newVal[1] + ); + + var scale = $scope.crop_image_width / $scope.image.width; + var selection = newVal[1]; + var ratioNums = newVal[0].split('x'); + + jcrop_api.setOptions({ + aspectRatio: ratioNums[0] / ratioNums[1] }); - $scope.setThumbStyles = function (image, selections) { - $scope.thumb_styles = $scope.thumb_styles || {}; + jcrop_api.setSelect([ + $scope.scaleNumber(selection.x0, scale), + $scope.scaleNumber(selection.y0, scale), + $scope.scaleNumber(selection.x1, scale), + $scope.scaleNumber(selection.y1, scale) + ]); + }); - for (var ratio in selections) { - $scope.thumb_styles[ratio] = $scope.computeThumbStyle( - image, $scope.thumb, ratio, selections[ratio] - ); - } - }; - - $scope.computeThumbStyle = function (image, thumb, ratio, selection) { - var scale, styles, h_or_w, selection_length, - s_width = selection.x1 - selection.x0, - s_height = selection.y1 - selection.y0; - if (s_width < s_height) { - h_or_w = 'height'; - selection_length = s_height; - } else { - h_or_w = 'width'; - selection_length = s_width; - } + $scope.setThumbStyles = function (image, selections) { + $scope.thumb_styles = $scope.thumb_styles || {}; - styles = {}; - scale = thumb[h_or_w] / selection_length; - styles['background'] = 'url('+$scope.image_url+')'; - styles['background-size'] = $scope.scaleNumber($scope.image.width, scale) + 'px'; - styles['background-position'] = '' + - '-' + $scope.scaleNumber(selection.x0, scale) +'px ' + - '-' + $scope.scaleNumber(selection.y0, scale) + 'px'; - styles['background-repeat'] = 'no-repeat'; - styles['height'] = $scope.scaleNumber(s_height, scale) + 'px'; - styles['width'] = $scope.scaleNumber(s_width, scale) + 'px'; - styles['top'] = '50%'; - styles['margin-top'] = '-' + ($scope.scaleNumber(s_height, scale) / 2) + 'px'; - - return styles; - }; - - $scope.scaleNumber = function (num, by_scale) { - return Math.floor(num * by_scale); - }; - - $scope.cancel = function () { - $modalInstance.dismiss('cancel'); - }; - - $scope.back = function () { - $scope.cropMode = false; + for (var ratio in selections) { + $scope.thumb_styles[ratio] = $scope.computeThumbStyle( + image, $scope.thumb, ratio, selections[ratio] + ); } + }; - $scope.save = function () { - // Should probably use a save directive here - $scope.processJcropSelection(jcrop_api.tellSelect()); - $bettycropper.update_selection( - $scope.image.id, - $scope.selectedCrop[0], - $scope.image.selections[$scope.selectedCrop[0]] - ).success(function (data) { - }); - }; + $scope.computeThumbStyle = function (image, thumb, ratio, selection) { + var scale, styles, h_or_w, selection_length, + s_width = selection.x1 - selection.x0, + s_height = selection.y1 - selection.y0; + if (s_width < s_height) { + h_or_w = 'height'; + selection_length = s_height; + } else { + h_or_w = 'width'; + selection_length = s_width; + } - $scope.saveAndNext = function () { - $scope.processJcropSelection(jcrop_api.tellSelect()); - $bettycropper.update_selection( - $scope.image.id, - $scope.selectedCrop[0], - $scope.image.selections[$scope.selectedCrop[0]] - ).success(function (data) { - var next = $scope.currentCrop + 1; - if (next >= $scope.ratioOrder.length) { - next = 0; - } - $scope.currentCrop = next; - $scope.selectedCrop = [ - $scope.ratioOrder[$scope.currentCrop], - $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] - ]; - }); - }; + styles = {}; + scale = thumb[h_or_w] / selection_length; + styles['background'] = 'url('+$scope.image_url+')'; + styles['background-size'] = $scope.scaleNumber($scope.image.width, scale) + 'px'; + styles['background-position'] = '' + + '-' + $scope.scaleNumber(selection.x0, scale) +'px ' + + '-' + $scope.scaleNumber(selection.y0, scale) + 'px'; + styles['background-repeat'] = 'no-repeat'; + styles['height'] = $scope.scaleNumber(s_height, scale) + 'px'; + styles['width'] = $scope.scaleNumber(s_width, scale) + 'px'; + styles['top'] = '50%'; + styles['margin-top'] = '-' + ($scope.scaleNumber(s_height, scale) / 2) + 'px'; + + return styles; + }; - $scope.isCurrentCrop = function (ratio) { - if ($scope.ratioOrder[$scope.currentCrop] === ratio) { - return {color: '#5bc0de'}; - } - }; - - $bettycropper.detail(id) - .success(function (data) { - $scope.image = data; - $scope.setThumbStyles($scope.image, $scope.image.selections); - $scope.ratioOrder = Object.keys($scope.image.selections); - $scope.currentCrop = 0; - }); + $scope.scaleNumber = function (num, by_scale) { + return Math.floor(num * by_scale); + }; + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); }; - $modal.open({ - templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", - controller: ModalInstanceCtrl, - resolve: { - id: function () { return scope.imageId; } + $scope.back = function () { + $scope.cropMode = false; + } + + $scope.saveAndQuit = function () { + // Should probably use a save directive here + $scope.processJcropSelection(jcrop_api.tellSelect()); + $bettycropper.update_selection( + $scope.image.id, + $scope.selectedCrop[0], + $scope.image.selections[$scope.selectedCrop[0]] + ).success(function (data) { + $modalInstance.close(); // Should be passing updated styling here + }); + }; + + $scope.saveAndNext = function () { + $scope.processJcropSelection(jcrop_api.tellSelect()); + $bettycropper.update_selection( + $scope.image.id, + $scope.selectedCrop[0], + $scope.image.selections[$scope.selectedCrop[0]] + ).success(function (data) { + var next = $scope.currentCrop + 1; + if (next >= $scope.ratioOrder.length) { + next = 0; + } + $scope.currentCrop = next; + $scope.selectedCrop = [ + $scope.ratioOrder[$scope.currentCrop], + $scope.image.selections[$scope.ratioOrder[$scope.currentCrop]] + ]; + }); + }; + + $scope.isCurrentCrop = function (ratio) { + if ($scope.ratioOrder[$scope.currentCrop] === ratio) { + return {color: '#5bc0de'}; } - }) - .result - .finally(function () { - element.remove(); - }) + }; + + $bettycropper.detail(id) + .success(function (data) { + $scope.image = data; + $scope.setThumbStyles($scope.image, $scope.image.selections); + $scope.ratioOrder = Object.keys($scope.image.selections); + $scope.currentCrop = 0; + }); + + }; + + return $modal.open({ + templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", + controller: ModalInstanceCtrl, + resolve: { + id: function () { return id; } + } + }).result; - } }; + $window.openImageCropModal = openImageCropModal; // THIS IS SOME BULLSHIT + return openImageCropModal; }) diff --git a/app/views/image-crop-modal.html b/app/views/image-crop-modal.html index b82ab71fc..3a23ebb4e 100644 --- a/app/views/image-crop-modal.html +++ b/app/views/image-crop-modal.html @@ -15,7 +15,7 @@
- +
From 914b9d38b72aa36ec095e0da6a735485fcf7ece4 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Tue, 29 Apr 2014 17:24:12 -0500 Subject: [PATCH 13/27] adding restangular back --- app/scripts/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/scripts/app.js b/app/scripts/app.js index d752c6194..48548640b 100644 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -18,6 +18,7 @@ angular.module('bulbsCmsApp', [ 'ngRoute', 'ui.bootstrap', 'ui.bootstrap.datetimepicker', + 'restangular', 'bettyCropper', 'jquery', 'underscore', From 9aab2a171e9dc52d2c984492d6eb68bc65e9dca7 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Tue, 29 Apr 2014 17:28:13 -0500 Subject: [PATCH 14/27] style fixes --- app/scripts/libraries/editor-cms-bridge.js | 6 +++--- app/scripts/modules/betty-cropper.js | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/scripts/libraries/editor-cms-bridge.js b/app/scripts/libraries/editor-cms-bridge.js index dbb2c6f4f..37d689f32 100644 --- a/app/scripts/libraries/editor-cms-bridge.js +++ b/app/scripts/libraries/editor-cms-bridge.js @@ -74,17 +74,17 @@ This bridges the embed module that the editor exposes & our custom image impleme function editImage(options) { - current_id = options.element.getAttribute("data-image-id"); + current_id = options.element.getAttribute('data-image-id'); openImageCropModal(current_id).then( function () { - $(options.element).attr("data-image-id", current_id); + $(options.element).attr('data-image-id', current_id); window.picturefill(); } ); function onDrawerImageChange(id) { - $(options.element).attr("data-image-id", id); + $(options.element).attr('data-image-id', id); window.picturefill(); } diff --git a/app/scripts/modules/betty-cropper.js b/app/scripts/modules/betty-cropper.js index 6cec91738..9f55c3cc9 100644 --- a/app/scripts/modules/betty-cropper.js +++ b/app/scripts/modules/betty-cropper.js @@ -19,7 +19,7 @@ angular.module('bettyCropper', []) }); }; - this.detail_patch = function (id, name, credit, selections) { + this.detailPatch = function (id, name, credit, selections) { return $http({ method: 'PATCH', url: IMAGE_SERVER_URL + '/api/' + id, @@ -54,7 +54,7 @@ angular.module('bettyCropper', []) }); }; - this.update_selection = function (id, ratio, selections) { + this.updateSelection = function (id, ratio, selections) { return $http({ method: 'POST', url: IMAGE_SERVER_URL + '/api/' + id + "/" + ratio, @@ -85,11 +85,11 @@ angular.module('bettyCropper', []) }); }; - this.orig_jpg = function (id, width) { + this.origJpg = function (id, width) { return this.url(id, 'original', width, 'jpg'); }; - this.orig_gif = function (id, width) { + this.origGif = function (id, width) { return this.url(id, 'original', width, 'gif'); }; From fa6d20bfe3c50b8acc92d9b3eaf85bf55fc4979c Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Wed, 30 Apr 2014 10:05:46 -0500 Subject: [PATCH 15/27] code style fixes --- app/scripts/modules/betty-cropper.js | 2 +- app/scripts/services/imagecropmodal.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/scripts/modules/betty-cropper.js b/app/scripts/modules/betty-cropper.js index 9f55c3cc9..bfc8594ac 100644 --- a/app/scripts/modules/betty-cropper.js +++ b/app/scripts/modules/betty-cropper.js @@ -1,5 +1,5 @@ angular.module('bettyCropper', []) - .service('$bettycropper', function $bettycropper($http, $interpolate, IMAGE_SERVER_URL, BC_API_KEY) { + .service('bettyCropper', function bettyCropper($http, $interpolate, IMAGE_SERVER_URL, BC_API_KEY) { /*\ diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index f9236199b..9c6d358e2 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -3,14 +3,14 @@ angular.module('bulbsCmsApp') .factory('openImageCropModal', function ($window, $document, $compile, $rootScope, $modal, routes) { var openImageCropModal = function (id) { - var ModalInstanceCtrl = function ($scope, $timeout, $bettycropper, $modalInstance, id) { + var ModalInstanceCtrl = function ($scope, $timeout, bettyCropper, $modalInstance, id) { var jcrop_api; $scope.cropMode = false; $scope.thumb = {height:180, width: 180}; $scope.preview_thumb = {height: 110, width: 110}; $scope.crop_image_width = 550; - $scope.image_url = $bettycropper.orig_jpg(id, $scope.crop_image_width); + $scope.image_url = bettyCropper.origJpg(id, $scope.crop_image_width); $scope.preview_style = {}; var setupCropper = function () { @@ -122,10 +122,10 @@ angular.module('bulbsCmsApp') styles = {}; scale = thumb[h_or_w] / selection_length; - styles['background'] = 'url('+$scope.image_url+')'; + styles['background'] = 'url(' + $scope.image_url + ')'; styles['background-size'] = $scope.scaleNumber($scope.image.width, scale) + 'px'; styles['background-position'] = '' + - '-' + $scope.scaleNumber(selection.x0, scale) +'px ' + + '-' + $scope.scaleNumber(selection.x0, scale) + 'px ' + '-' + $scope.scaleNumber(selection.y0, scale) + 'px'; styles['background-repeat'] = 'no-repeat'; styles['height'] = $scope.scaleNumber(s_height, scale) + 'px'; @@ -151,7 +151,7 @@ angular.module('bulbsCmsApp') $scope.saveAndQuit = function () { // Should probably use a save directive here $scope.processJcropSelection(jcrop_api.tellSelect()); - $bettycropper.update_selection( + bettyCropper.update_selection( $scope.image.id, $scope.selectedCrop[0], $scope.image.selections[$scope.selectedCrop[0]] @@ -162,7 +162,7 @@ angular.module('bulbsCmsApp') $scope.saveAndNext = function () { $scope.processJcropSelection(jcrop_api.tellSelect()); - $bettycropper.update_selection( + bettyCropper.update_selection( $scope.image.id, $scope.selectedCrop[0], $scope.image.selections[$scope.selectedCrop[0]] @@ -185,7 +185,7 @@ angular.module('bulbsCmsApp') } }; - $bettycropper.detail(id) + bettyCropper.detail(id) .success(function (data) { $scope.image = data; $scope.setThumbStyles($scope.image, $scope.image.selections); From 48ac58452b505749988657f39918da06de994dc4 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Wed, 30 Apr 2014 10:19:03 -0500 Subject: [PATCH 16/27] to deploy to test --- .gitignore | 1 - dist/.htaccess | 543 + dist/404.html | 157 + .../.bower.json | 43 + .../angular-bootstrap-datetimepicker/LICENSE | 18 + .../README.md | 244 + .../bower.json | 34 + .../karma.conf.js | 91 + .../src/css/datetimepicker.css | 364 + .../src/js/datetimepicker.js | 341 + .../angular-bootstrap/.bower.json | 23 + .../angular-bootstrap/bower.json | 11 + .../angular-bootstrap/ui-bootstrap-tpls.js | 3677 ++ .../ui-bootstrap-tpls.min.js | 9 + .../angular-bootstrap/ui-bootstrap.js | 3427 ++ .../angular-bootstrap/ui-bootstrap.min.js | 9 + .../angular-cookies/.bower.json | 18 + .../angular-cookies/README.md | 54 + .../angular-cookies/angular-cookies.js | 196 + .../angular-cookies/angular-cookies.min.js | 8 + .../angular-cookies.min.js.map | 8 + .../angular-cookies/bower.json | 8 + .../angular-mocks/.bower.json | 18 + dist/bower_components/angular-mocks/README.md | 42 + .../angular-mocks/angular-mocks.js | 2136 + .../bower_components/angular-mocks/bower.json | 8 + .../angular-resource/.bower.json | 18 + .../angular-resource/README.md | 54 + .../angular-resource/angular-resource.js | 610 + .../angular-resource/angular-resource.min.js | 13 + .../angular-resource.min.js.map | 8 + .../angular-resource/bower.json | 8 + .../angular-route/.bower.json | 18 + dist/bower_components/angular-route/README.md | 54 + .../angular-route/angular-route.js | 927 + .../angular-route/angular-route.min.js | 14 + .../angular-route/angular-route.min.js.map | 8 + .../bower_components/angular-route/bower.json | 8 + .../angular-sanitize/.bower.json | 18 + .../angular-sanitize/README.md | 54 + .../angular-sanitize/angular-sanitize.js | 624 + .../angular-sanitize/angular-sanitize.min.js | 14 + .../angular-sanitize.min.js.map | 8 + .../angular-sanitize/bower.json | 8 + .../angular-scenario/.bower.json | 18 + .../angular-scenario/README.md | 42 + .../angular-scenario/angular-scenario.js | 32560 ++++++++++++++++ .../angular-scenario/bower.json | 8 + .../jstd-scenario-adapter-config.js | 6 + .../angular-scenario/jstd-scenario-adapter.js | 185 + dist/bower_components/angular/.bower.json | 16 + dist/bower_components/angular/README.md | 48 + dist/bower_components/angular/angular-csp.css | 13 + dist/bower_components/angular/angular.js | 20554 ++++++++++ dist/bower_components/angular/angular.min.js | 202 + .../angular/angular.min.js.gzip | Bin 0 -> 36884 bytes .../angular/angular.min.js.map | 8 + dist/bower_components/angular/bower.json | 7 + .../bootstrap-datetimepicker/.bower.json | 20 + .../bootstrap-datetimepicker/.gitignore | 6 + .../bootstrap-datetimepicker/.gitmodules | 3 + .../bootstrap-datetimepicker/.lvimrc | 8 + .../bootstrap-datetimepicker/.npmignore | 12 + .../bootstrap-datetimepicker/CONTRIBUTING.md | 12 + .../bootstrap-datetimepicker/LICENSE | 201 + .../bootstrap-datetimepicker/Makefile | 22 + .../bootstrap-datetimepicker/README.md | 4 + .../css/bootstrap-datetimepicker.min.css | 9 + .../build/js/bootstrap-datetimepicker.min.js | 27 + .../bootstrap-datetimepicker/component.json | 9 + .../bootstrap-datetimepicker/package.json | 23 + .../src/js/bootstrap-datetimepicker.js | 1306 + .../js/locales/bootstrap-datetimepicker.bg.js | 14 + .../js/locales/bootstrap-datetimepicker.cs.js | 14 + .../js/locales/bootstrap-datetimepicker.da.js | 14 + .../js/locales/bootstrap-datetimepicker.de.js | 14 + .../js/locales/bootstrap-datetimepicker.es.js | 14 + .../locales/bootstrap-datetimepicker.fa-IR.js | 14 + .../js/locales/bootstrap-datetimepicker.fi.js | 14 + .../js/locales/bootstrap-datetimepicker.fo.js | 14 + .../js/locales/bootstrap-datetimepicker.fr.js | 14 + .../js/locales/bootstrap-datetimepicker.hr.js | 13 + .../js/locales/bootstrap-datetimepicker.hu.js | 14 + .../js/locales/bootstrap-datetimepicker.id.js | 13 + .../js/locales/bootstrap-datetimepicker.is.js | 14 + .../js/locales/bootstrap-datetimepicker.it.js | 14 + .../js/locales/bootstrap-datetimepicker.ja.js | 13 + .../js/locales/bootstrap-datetimepicker.kr.js | 13 + .../js/locales/bootstrap-datetimepicker.lt.js | 16 + .../js/locales/bootstrap-datetimepicker.lv.js | 16 + .../js/locales/bootstrap-datetimepicker.ms.js | 14 + .../js/locales/bootstrap-datetimepicker.nb.js | 14 + .../js/locales/bootstrap-datetimepicker.nl.js | 14 + .../js/locales/bootstrap-datetimepicker.pl.js | 15 + .../locales/bootstrap-datetimepicker.pt-BR.js | 14 + .../js/locales/bootstrap-datetimepicker.pt.js | 14 + .../js/locales/bootstrap-datetimepicker.ro.js | 15 + .../bootstrap-datetimepicker.rs-latin.js | 14 + .../js/locales/bootstrap-datetimepicker.rs.js | 14 + .../js/locales/bootstrap-datetimepicker.ru.js | 14 + .../js/locales/bootstrap-datetimepicker.sk.js | 14 + .../js/locales/bootstrap-datetimepicker.sl.js | 14 + .../js/locales/bootstrap-datetimepicker.sv.js | 14 + .../js/locales/bootstrap-datetimepicker.th.js | 14 + .../js/locales/bootstrap-datetimepicker.tr.js | 15 + .../locales/bootstrap-datetimepicker.zh-CN.js | 14 + .../locales/bootstrap-datetimepicker.zh-TW.js | 13 + .../src/less/bootstrap-datetimepicker.less | 248 + .../basic-test-cases/TEMPLATE/template.html | 30 + .../no-collapsible/index.html | 30 + .../test/issues.coffee | 80 + .../bootstrap-datetimepicker/test/run.sh | 36 + .../test/specs.coffee | 343 + .../bootstrap-datetimepicker/test/test.html | 40 + .../test/utils.coffee | 38 + .../bootstrap-switch/.bower.json | 25 + .../bootstrap-switch/.gitignore | 3 + dist/bower_components/bootstrap-switch/CNAME | 1 + .../bootstrap-switch/CONTRIBUTING.md | 21 + .../bootstrap-switch/Gruntfile.coffee | 116 + .../bower_components/bootstrap-switch/LICENSE | 176 + .../bootstrap-switch/README.md | 44 + .../bootstrap-switch/bower.json | 15 + .../build/css/bootstrap2/bootstrap-switch.css | 446 + .../css/bootstrap2/bootstrap-switch.min.css | 22 + .../build/css/bootstrap3/bootstrap-switch.css | 184 + .../css/bootstrap3/bootstrap-switch.min.css | 22 + .../build/js/bootstrap-switch.js | 394 + .../build/js/bootstrap-switch.min.js | 22 + .../bootstrap-switch/composer.json | 33 + .../bootstrap-switch/index.html | 410 + .../bootstrap-switch/package.json | 55 + .../src/coffee/bootstrap-switch.coffee | 340 + .../src/less/bootstrap2/bootstrap-switch.less | 183 + .../src/less/bootstrap2/mixins.less | 702 + .../src/less/bootstrap2/variables.less | 301 + .../src/less/bootstrap3/bootstrap-switch.less | 185 + .../src/less/bootstrap3/mixins.less | 873 + .../src/less/bootstrap3/variables.less | 645 + dist/bower_components/bootstrap/.bower.json | 34 + dist/bower_components/bootstrap/Gruntfile.js | 418 + dist/bower_components/bootstrap/LICENSE | 21 + dist/bower_components/bootstrap/README.md | 173 + dist/bower_components/bootstrap/bower.json | 24 + .../bootstrap/browserstack.json | 44 + .../bootstrap/dist/css/bootstrap-theme.css | 347 + .../dist/css/bootstrap-theme.css.map | 1 + .../dist/css/bootstrap-theme.min.css | 7 + .../bootstrap/dist/css/bootstrap.css | 5831 +++ .../bootstrap/dist/css/bootstrap.css.map | 1 + .../bootstrap/dist/css/bootstrap.min.css | 7 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20290 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41236 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23292 bytes .../bootstrap/dist/js/bootstrap.js | 1951 + .../bootstrap/dist/js/bootstrap.min.js | 6 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20290 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41236 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23292 bytes dist/bower_components/bootstrap/js/affix.js | 137 + dist/bower_components/bootstrap/js/alert.js | 88 + dist/bower_components/bootstrap/js/button.js | 107 + .../bower_components/bootstrap/js/carousel.js | 205 + .../bower_components/bootstrap/js/collapse.js | 170 + .../bower_components/bootstrap/js/dropdown.js | 147 + dist/bower_components/bootstrap/js/modal.js | 243 + dist/bower_components/bootstrap/js/popover.js | 110 + .../bootstrap/js/scrollspy.js | 153 + dist/bower_components/bootstrap/js/tab.js | 125 + dist/bower_components/bootstrap/js/tooltip.js | 399 + .../bootstrap/js/transition.js | 48 + .../bootstrap/less/alerts.less | 67 + .../bootstrap/less/badges.less | 55 + .../bootstrap/less/bootstrap.less | 49 + .../bootstrap/less/breadcrumbs.less | 26 + .../bootstrap/less/button-groups.less | 226 + .../bootstrap/less/buttons.less | 155 + .../bootstrap/less/carousel.less | 232 + .../bootstrap/less/close.less | 33 + .../bower_components/bootstrap/less/code.less | 63 + .../bootstrap/less/component-animations.less | 29 + .../bootstrap/less/dropdowns.less | 213 + .../bootstrap/less/forms.less | 419 + .../bootstrap/less/glyphicons.less | 233 + .../bower_components/bootstrap/less/grid.less | 100 + .../bootstrap/less/input-groups.less | 157 + .../bootstrap/less/jumbotron.less | 44 + .../bootstrap/less/labels.less | 64 + .../bootstrap/less/list-group.less | 110 + .../bootstrap/less/media.less | 56 + .../bootstrap/less/mixins.less | 926 + .../bootstrap/less/modals.less | 138 + .../bootstrap/less/navbar.less | 616 + .../bower_components/bootstrap/less/navs.less | 242 + .../bootstrap/less/normalize.less | 423 + .../bootstrap/less/pager.less | 55 + .../bootstrap/less/pagination.less | 88 + .../bootstrap/less/panels.less | 230 + .../bootstrap/less/popovers.less | 133 + .../bootstrap/less/print.less | 101 + .../bootstrap/less/progress-bars.less | 80 + .../bootstrap/less/responsive-utilities.less | 93 + .../bootstrap/less/scaffolding.less | 134 + .../bootstrap/less/tables.less | 233 + .../bootstrap/less/theme.less | 247 + .../bootstrap/less/thumbnails.less | 36 + .../bootstrap/less/tooltip.less | 95 + .../bower_components/bootstrap/less/type.less | 296 + .../bootstrap/less/utilities.less | 56 + .../bootstrap/less/variables.less | 827 + .../bootstrap/less/wells.less | 29 + dist/bower_components/bootstrap/package.json | 71 + .../bootstrap/test-infra/README.md | 100 + .../test-infra/npm-shrinkwrap.canonical.json | 1 + .../bootstrap/test-infra/requirements.txt | 1 + .../bootstrap/test-infra/s3_cache.py | 107 + .../bootstrap/test-infra/sauce_browsers.yml | 83 + .../bootstrap/test-infra/shrinkwrap.js | 24 + .../test-infra/uncached-npm-install.sh | 4 + dist/bower_components/es5-shim/.bower.json | 14 + dist/bower_components/es5-shim/.gitignore | 2 + dist/bower_components/es5-shim/CHANGES | 93 + .../bower_components/es5-shim/CONTRIBUTORS.md | 25 + dist/bower_components/es5-shim/LICENSE | 19 + dist/bower_components/es5-shim/README.md | 161 + dist/bower_components/es5-shim/es5-sham.js | 444 + dist/bower_components/es5-shim/es5-sham.map | 1 + .../bower_components/es5-shim/es5-sham.min.js | 4 + dist/bower_components/es5-shim/es5-shim.js | 1314 + dist/bower_components/es5-shim/es5-shim.map | 1 + .../bower_components/es5-shim/es5-shim.min.js | 4 + dist/bower_components/es5-shim/package.json | 34 + .../es5-shim/tests/helpers/h-kill.js | 64 + .../es5-shim/tests/helpers/h-matchers.js | 34 + .../es5-shim/tests/helpers/h.js | 3 + .../es5-shim/tests/index.html | 64 + .../es5-shim/tests/index.min.html | 63 + .../es5-shim/tests/lib/jasmine-html.js | 190 + .../es5-shim/tests/lib/jasmine.css | 166 + .../es5-shim/tests/lib/jasmine.js | 2477 ++ .../es5-shim/tests/lib/jasmine_favicon.png | Bin 0 -> 905 bytes .../es5-shim/tests/lib/json2.js | 478 + .../es5-shim/tests/spec/s-array.js | 1223 + .../es5-shim/tests/spec/s-date.js | 152 + .../es5-shim/tests/spec/s-function.js | 147 + .../es5-shim/tests/spec/s-number.js | 14 + .../es5-shim/tests/spec/s-object.js | 181 + .../es5-shim/tests/spec/s-string.js | 204 + .../bower_components/font-awesome/.bower.json | 14 + dist/bower_components/font-awesome/.gitignore | 32 + .../font-awesome/CONTRIBUTING.md | 75 + dist/bower_components/font-awesome/Gemfile | 4 + .../font-awesome/Gemfile.lock | 46 + dist/bower_components/font-awesome/README.md | 77 + .../bower_components/font-awesome/_config.yml | 58 + .../font-awesome/component.json | 20 + .../font-awesome/composer.json | 27 + .../font-awesome/css/font-awesome.css | 1338 + .../font-awesome/css/font-awesome.min.css | 4 + .../font-awesome/fonts/FontAwesome.otf | Bin 0 -> 62856 bytes .../fonts/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../fonts/fontawesome-webfont.svg | 414 + .../fonts/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../fonts/fontawesome-webfont.woff | Bin 0 -> 44432 bytes .../font-awesome/less/bordered-pulled.less | 16 + .../font-awesome/less/core.less | 12 + .../font-awesome/less/extras.less | 2 + .../font-awesome/less/fixed-width.less | 6 + .../font-awesome/less/font-awesome.less | 17 + .../font-awesome/less/icons.less | 412 + .../font-awesome/less/larger.less | 13 + .../font-awesome/less/list.less | 19 + .../font-awesome/less/mixins.less | 20 + .../font-awesome/less/path.less | 14 + .../font-awesome/less/rotated-flipped.less | 9 + .../font-awesome/less/spinning.less | 30 + .../font-awesome/less/stacked.less | 20 + .../font-awesome/less/variables.less | 381 + .../font-awesome/package.json | 43 + .../font-awesome/scss/_bordered-pulled.scss | 16 + .../font-awesome/scss/_core.scss | 12 + .../font-awesome/scss/_extras.scss | 44 + .../font-awesome/scss/_fixed-width.scss | 6 + .../font-awesome/scss/_icons.scss | 412 + .../font-awesome/scss/_larger.scss | 13 + .../font-awesome/scss/_list.scss | 19 + .../font-awesome/scss/_mixins.scss | 20 + .../font-awesome/scss/_path.scss | 14 + .../font-awesome/scss/_rotated-flipped.scss | 9 + .../font-awesome/scss/_spinning.scss | 30 + .../font-awesome/scss/_stacked.scss | 20 + .../font-awesome/scss/_variables.scss | 381 + .../font-awesome/scss/font-awesome.scss | 17 + .../font-awesome/src/3.2.1/CNAME | 1 + .../font-awesome/src/3.2.1/Makefile | 36 + .../src/3.2.1/assets/css/prettify.css | 30 + .../src/3.2.1/assets/css/pygments.css | 71 + .../src/3.2.1/assets/css/site.css | 1154 + .../src/3.2.1/assets/font-awesome.zip | Bin 0 -> 276410 bytes .../font-awesome/css/font-awesome-ie7.css | 1203 + .../font-awesome/css/font-awesome-ie7.min.css | 384 + .../assets/font-awesome/css/font-awesome.css | 1479 + .../font-awesome/css/font-awesome.min.css | 403 + .../assets/font-awesome/font/FontAwesome.otf | Bin 0 -> 61896 bytes .../font-awesome/font/fontawesome-webfont.eot | Bin 0 -> 37405 bytes .../font-awesome/font/fontawesome-webfont.svg | 399 + .../font-awesome/font/fontawesome-webfont.ttf | Bin 0 -> 79076 bytes .../font/fontawesome-webfont.woff | Bin 0 -> 43572 bytes .../assets/font-awesome/less/bootstrap.less | 84 + .../3.2.1/assets/font-awesome/less/core.less | 129 + .../assets/font-awesome/less/extras.less | 93 + .../font-awesome/less/font-awesome-ie7.less | 1953 + .../font-awesome/less/font-awesome.less | 33 + .../3.2.1/assets/font-awesome/less/icons.less | 381 + .../assets/font-awesome/less/mixins.less | 48 + .../3.2.1/assets/font-awesome/less/path.less | 14 + .../assets/font-awesome/less/variables.less | 735 + .../assets/font-awesome/scss/_bootstrap.scss | 84 + .../3.2.1/assets/font-awesome/scss/_core.scss | 129 + .../assets/font-awesome/scss/_extras.scss | 93 + .../assets/font-awesome/scss/_icons.scss | 381 + .../assets/font-awesome/scss/_mixins.scss | 48 + .../3.2.1/assets/font-awesome/scss/_path.scss | 14 + .../assets/font-awesome/scss/_variables.scss | 734 + .../font-awesome/scss/font-awesome-ie7.scss | 1953 + .../font-awesome/scss/font-awesome.scss | 33 + .../src/3.2.1/assets/ico/favicon.ico | Bin 0 -> 1150 bytes .../3.2.1/assets/img/contribution-sample.png | Bin 0 -> 2441 bytes .../src/3.2.1/assets/img/fort_awesome.jpg | Bin 0 -> 114822 bytes .../assets/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../3.2.1/assets/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes .../src/3.2.1/assets/img/icon-flag.pdf | Bin 0 -> 184736 bytes .../assets/js/ZeroClipboard-1.1.7.min.js | 8 + .../3.2.1/assets/js/ZeroClipboard-1.1.7.swf | Bin 0 -> 1635 bytes .../src/3.2.1/assets/js/backbone.min.js | 37 + .../3.2.1/assets/js/bootstrap-2.3.1.min.js | 6 + .../src/3.2.1/assets/js/bootstrap-222.min.js | 6 + .../src/3.2.1/assets/js/jquery-1.7.1.min.js | 4 + .../src/3.2.1/assets/js/prettify.min.js | 28 + .../font-awesome/src/3.2.1/assets/js/site.js | 38 + .../src/3.2.1/assets/js/underscore.min.js | 31 + .../less/bootstrap-2.3.2/accordion.less | 34 + .../assets/less/bootstrap-2.3.2/alerts.less | 79 + .../less/bootstrap-2.3.2/bootstrap.less | 63 + .../less/bootstrap-2.3.2/breadcrumbs.less | 24 + .../less/bootstrap-2.3.2/button-groups.less | 229 + .../assets/less/bootstrap-2.3.2/buttons.less | 228 + .../assets/less/bootstrap-2.3.2/carousel.less | 158 + .../assets/less/bootstrap-2.3.2/close.less | 32 + .../assets/less/bootstrap-2.3.2/code.less | 61 + .../bootstrap-2.3.2/component-animations.less | 22 + .../less/bootstrap-2.3.2/dropdowns.less | 248 + .../assets/less/bootstrap-2.3.2/forms.less | 690 + .../assets/less/bootstrap-2.3.2/grid.less | 21 + .../less/bootstrap-2.3.2/hero-unit.less | 25 + .../less/bootstrap-2.3.2/labels-badges.less | 84 + .../assets/less/bootstrap-2.3.2/layouts.less | 16 + .../assets/less/bootstrap-2.3.2/media.less | 55 + .../assets/less/bootstrap-2.3.2/mixins.less | 702 + .../assets/less/bootstrap-2.3.2/modals.less | 95 + .../assets/less/bootstrap-2.3.2/navbar.less | 497 + .../assets/less/bootstrap-2.3.2/navs.less | 409 + .../assets/less/bootstrap-2.3.2/pager.less | 43 + .../less/bootstrap-2.3.2/pagination.less | 123 + .../assets/less/bootstrap-2.3.2/popovers.less | 133 + .../less/bootstrap-2.3.2/progress-bars.less | 122 + .../assets/less/bootstrap-2.3.2/reset.less | 216 + .../responsive-1200px-min.less | 28 + .../bootstrap-2.3.2/responsive-767px-max.less | 193 + .../responsive-768px-979px.less | 19 + .../bootstrap-2.3.2/responsive-navbar.less | 189 + .../bootstrap-2.3.2/responsive-utilities.less | 59 + .../less/bootstrap-2.3.2/responsive.less | 48 + .../less/bootstrap-2.3.2/scaffolding.less | 53 + .../assets/less/bootstrap-2.3.2/sprites.less | 197 + .../assets/less/bootstrap-2.3.2/tables.less | 244 + .../less/bootstrap-2.3.2/thumbnails.less | 53 + .../assets/less/bootstrap-2.3.2/tooltip.less | 70 + .../assets/less/bootstrap-2.3.2/type.less | 247 + .../less/bootstrap-2.3.2/utilities.less | 30 + .../less/bootstrap-2.3.2/variables.less | 301 + .../assets/less/bootstrap-2.3.2/wells.less | 29 + .../src/3.2.1/assets/less/lazy.less | 85 + .../src/3.2.1/assets/less/mixins.less | 58 + .../assets/less/responsive-1200px-min.less | 56 + .../assets/less/responsive-767px-max.less | 83 + .../assets/less/responsive-768px-979px.less | 67 + .../3.2.1/assets/less/responsive-navbar.less | 11 + .../src/3.2.1/assets/less/responsive.less | 53 + .../src/3.2.1/assets/less/site.less | 352 + .../src/3.2.1/assets/less/sticky-footer.less | 17 + .../src/3.2.1/assets/less/variables.less | 347 + .../src/3.2.1/cheatsheet/index.html | 2379 ++ .../src/3.2.1/community/index.html | 354 + .../font-awesome/src/3.2.1/design.html | 1 + .../src/3.2.1/examples/index.html | 671 + .../src/3.2.1/get-started/index.html | 299 + .../src/3.2.1/icon/adjust/index.html | 208 + .../src/3.2.1/icon/adn/index.html | 208 + .../src/3.2.1/icon/align-center/index.html | 208 + .../src/3.2.1/icon/align-justify/index.html | 208 + .../src/3.2.1/icon/align-left/index.html | 208 + .../src/3.2.1/icon/align-right/index.html | 208 + .../src/3.2.1/icon/ambulance/index.html | 208 + .../src/3.2.1/icon/anchor/index.html | 208 + .../src/3.2.1/icon/android/index.html | 208 + .../src/3.2.1/icon/angle-down/index.html | 208 + .../src/3.2.1/icon/angle-left/index.html | 208 + .../src/3.2.1/icon/angle-right/index.html | 208 + .../src/3.2.1/icon/angle-up/index.html | 208 + .../src/3.2.1/icon/apple/index.html | 208 + .../src/3.2.1/icon/archive/index.html | 208 + .../src/3.2.1/icon/arrow-down/index.html | 208 + .../src/3.2.1/icon/arrow-left/index.html | 208 + .../src/3.2.1/icon/arrow-right/index.html | 208 + .../src/3.2.1/icon/arrow-up/index.html | 208 + .../src/3.2.1/icon/asterisk/index.html | 208 + .../src/3.2.1/icon/backward/index.html | 208 + .../src/3.2.1/icon/ban-circle/index.html | 208 + .../src/3.2.1/icon/bar-chart/index.html | 208 + .../src/3.2.1/icon/barcode/index.html | 208 + .../src/3.2.1/icon/beaker/index.html | 208 + .../src/3.2.1/icon/beer/index.html | 208 + .../src/3.2.1/icon/bell-alt/index.html | 208 + .../src/3.2.1/icon/bell/index.html | 208 + .../src/3.2.1/icon/bitbucket-sign/index.html | 208 + .../src/3.2.1/icon/bitbucket/index.html | 208 + .../src/3.2.1/icon/bold/index.html | 208 + .../src/3.2.1/icon/bolt/index.html | 208 + .../src/3.2.1/icon/book/index.html | 208 + .../src/3.2.1/icon/bookmark-empty/index.html | 208 + .../src/3.2.1/icon/bookmark/index.html | 208 + .../src/3.2.1/icon/briefcase/index.html | 208 + .../src/3.2.1/icon/btc/index.html | 215 + .../src/3.2.1/icon/bug/index.html | 208 + .../src/3.2.1/icon/building/index.html | 208 + .../src/3.2.1/icon/bullhorn/index.html | 208 + .../src/3.2.1/icon/bullseye/index.html | 208 + .../src/3.2.1/icon/calendar-empty/index.html | 208 + .../src/3.2.1/icon/calendar/index.html | 208 + .../src/3.2.1/icon/camera-retro/index.html | 208 + .../src/3.2.1/icon/camera/index.html | 208 + .../src/3.2.1/icon/caret-down/index.html | 208 + .../src/3.2.1/icon/caret-left/index.html | 208 + .../src/3.2.1/icon/caret-right/index.html | 208 + .../src/3.2.1/icon/caret-up/index.html | 208 + .../src/3.2.1/icon/certificate/index.html | 208 + .../src/3.2.1/icon/check-empty/index.html | 213 + .../src/3.2.1/icon/check-minus/index.html | 208 + .../src/3.2.1/icon/check-sign/index.html | 208 + .../src/3.2.1/icon/check/index.html | 208 + .../src/3.2.1/icon/chevron-down/index.html | 208 + .../src/3.2.1/icon/chevron-left/index.html | 208 + .../src/3.2.1/icon/chevron-right/index.html | 208 + .../3.2.1/icon/chevron-sign-down/index.html | 208 + .../3.2.1/icon/chevron-sign-left/index.html | 208 + .../3.2.1/icon/chevron-sign-right/index.html | 208 + .../src/3.2.1/icon/chevron-sign-up/index.html | 208 + .../src/3.2.1/icon/chevron-up/index.html | 208 + .../3.2.1/icon/circle-arrow-down/index.html | 208 + .../3.2.1/icon/circle-arrow-left/index.html | 208 + .../3.2.1/icon/circle-arrow-right/index.html | 208 + .../src/3.2.1/icon/circle-arrow-up/index.html | 208 + .../src/3.2.1/icon/circle-blank/index.html | 208 + .../src/3.2.1/icon/circle/index.html | 208 + .../src/3.2.1/icon/cloud-download/index.html | 208 + .../src/3.2.1/icon/cloud-upload/index.html | 208 + .../src/3.2.1/icon/cloud/index.html | 208 + .../src/3.2.1/icon/cny/index.html | 213 + .../src/3.2.1/icon/code-fork/index.html | 208 + .../src/3.2.1/icon/code/index.html | 208 + .../src/3.2.1/icon/coffee/index.html | 208 + .../src/3.2.1/icon/cog/index.html | 213 + .../src/3.2.1/icon/cogs/index.html | 213 + .../src/3.2.1/icon/collapse-alt/index.html | 208 + .../src/3.2.1/icon/collapse-top/index.html | 208 + .../src/3.2.1/icon/collapse/index.html | 208 + .../src/3.2.1/icon/columns/index.html | 208 + .../src/3.2.1/icon/comment-alt/index.html | 208 + .../src/3.2.1/icon/comment/index.html | 208 + .../src/3.2.1/icon/comments-alt/index.html | 208 + .../src/3.2.1/icon/comments/index.html | 208 + .../src/3.2.1/icon/compass/index.html | 208 + .../src/3.2.1/icon/copy/index.html | 208 + .../src/3.2.1/icon/credit-card/index.html | 208 + .../src/3.2.1/icon/crop/index.html | 208 + .../src/3.2.1/icon/css3/index.html | 208 + .../src/3.2.1/icon/cut/index.html | 208 + .../src/3.2.1/icon/dashboard/index.html | 208 + .../src/3.2.1/icon/desktop/index.html | 208 + .../3.2.1/icon/double-angle-down/index.html | 208 + .../3.2.1/icon/double-angle-left/index.html | 208 + .../3.2.1/icon/double-angle-right/index.html | 208 + .../src/3.2.1/icon/double-angle-up/index.html | 208 + .../src/3.2.1/icon/download-alt/index.html | 208 + .../src/3.2.1/icon/download/index.html | 208 + .../src/3.2.1/icon/dribbble/index.html | 208 + .../src/3.2.1/icon/dropbox/index.html | 208 + .../src/3.2.1/icon/edit-sign/index.html | 208 + .../src/3.2.1/icon/edit/index.html | 208 + .../src/3.2.1/icon/eject/index.html | 208 + .../3.2.1/icon/ellipsis-horizontal/index.html | 208 + .../3.2.1/icon/ellipsis-vertical/index.html | 208 + .../src/3.2.1/icon/envelope-alt/index.html | 208 + .../src/3.2.1/icon/envelope/index.html | 208 + .../src/3.2.1/icon/eraser/index.html | 210 + .../src/3.2.1/icon/eur/index.html | 213 + .../src/3.2.1/icon/exchange/index.html | 208 + .../3.2.1/icon/exclamation-sign/index.html | 208 + .../src/3.2.1/icon/exclamation/index.html | 208 + .../src/3.2.1/icon/expand-alt/index.html | 208 + .../src/3.2.1/icon/expand/index.html | 208 + .../3.2.1/icon/external-link-sign/index.html | 208 + .../src/3.2.1/icon/external-link/index.html | 208 + .../src/3.2.1/icon/eye-close/index.html | 208 + .../src/3.2.1/icon/eye-open/index.html | 208 + .../src/3.2.1/icon/facebook-sign/index.html | 208 + .../src/3.2.1/icon/facebook/index.html | 208 + .../src/3.2.1/icon/facetime-video/index.html | 208 + .../src/3.2.1/icon/fast-backward/index.html | 208 + .../src/3.2.1/icon/fast-forward/index.html | 208 + .../src/3.2.1/icon/female/index.html | 208 + .../src/3.2.1/icon/fighter-jet/index.html | 208 + .../src/3.2.1/icon/file-alt/index.html | 208 + .../src/3.2.1/icon/file-text-alt/index.html | 208 + .../src/3.2.1/icon/file-text/index.html | 208 + .../src/3.2.1/icon/file/index.html | 208 + .../src/3.2.1/icon/film/index.html | 208 + .../src/3.2.1/icon/filter/index.html | 208 + .../3.2.1/icon/fire-extinguisher/index.html | 208 + .../src/3.2.1/icon/fire/index.html | 208 + .../src/3.2.1/icon/flag-alt/index.html | 208 + .../src/3.2.1/icon/flag-checkered/index.html | 208 + .../src/3.2.1/icon/flag/index.html | 208 + .../src/3.2.1/icon/flickr/index.html | 208 + .../3.2.1/icon/folder-close-alt/index.html | 208 + .../src/3.2.1/icon/folder-close/index.html | 208 + .../src/3.2.1/icon/folder-open-alt/index.html | 208 + .../src/3.2.1/icon/folder-open/index.html | 208 + .../src/3.2.1/icon/font/index.html | 208 + .../src/3.2.1/icon/food/index.html | 208 + .../src/3.2.1/icon/forward/index.html | 208 + .../src/3.2.1/icon/foursquare/index.html | 208 + .../src/3.2.1/icon/frown/index.html | 208 + .../src/3.2.1/icon/fullscreen/index.html | 208 + .../src/3.2.1/icon/gamepad/index.html | 208 + .../src/3.2.1/icon/gbp/index.html | 208 + .../src/3.2.1/icon/gift/index.html | 208 + .../src/3.2.1/icon/github-alt/index.html | 208 + .../src/3.2.1/icon/github-sign/index.html | 208 + .../src/3.2.1/icon/github/index.html | 208 + .../src/3.2.1/icon/gittip/index.html | 208 + .../src/3.2.1/icon/glass/index.html | 208 + .../src/3.2.1/icon/globe/index.html | 208 + .../3.2.1/icon/google-plus-sign/index.html | 208 + .../src/3.2.1/icon/google-plus/index.html | 208 + .../src/3.2.1/icon/group/index.html | 208 + .../src/3.2.1/icon/h-sign/index.html | 208 + .../src/3.2.1/icon/hand-down/index.html | 208 + .../src/3.2.1/icon/hand-left/index.html | 208 + .../src/3.2.1/icon/hand-right/index.html | 208 + .../src/3.2.1/icon/hand-up/index.html | 208 + .../src/3.2.1/icon/hdd/index.html | 208 + .../src/3.2.1/icon/headphones/index.html | 208 + .../src/3.2.1/icon/heart-empty/index.html | 208 + .../src/3.2.1/icon/heart/index.html | 208 + .../src/3.2.1/icon/home/index.html | 208 + .../src/3.2.1/icon/hospital/index.html | 208 + .../src/3.2.1/icon/html5/index.html | 208 + .../src/3.2.1/icon/inbox/index.html | 208 + .../src/3.2.1/icon/indent-left/index.html | 208 + .../src/3.2.1/icon/indent-right/index.html | 208 + .../src/3.2.1/icon/info-sign/index.html | 208 + .../src/3.2.1/icon/info/index.html | 208 + .../src/3.2.1/icon/inr/index.html | 213 + .../src/3.2.1/icon/instagram/index.html | 208 + .../src/3.2.1/icon/italic/index.html | 208 + .../src/3.2.1/icon/jpy/index.html | 213 + .../src/3.2.1/icon/key/index.html | 208 + .../src/3.2.1/icon/keyboard/index.html | 208 + .../src/3.2.1/icon/krw/index.html | 213 + .../src/3.2.1/icon/laptop/index.html | 208 + .../src/3.2.1/icon/leaf/index.html | 208 + .../src/3.2.1/icon/legal/index.html | 208 + .../src/3.2.1/icon/lemon/index.html | 208 + .../src/3.2.1/icon/level-down/index.html | 208 + .../src/3.2.1/icon/level-up/index.html | 208 + .../src/3.2.1/icon/lightbulb/index.html | 208 + .../src/3.2.1/icon/link/index.html | 208 + .../src/3.2.1/icon/linkedin-sign/index.html | 208 + .../src/3.2.1/icon/linkedin/index.html | 208 + .../src/3.2.1/icon/linux/index.html | 208 + .../src/3.2.1/icon/list-alt/index.html | 208 + .../src/3.2.1/icon/list-ol/index.html | 208 + .../src/3.2.1/icon/list-ul/index.html | 208 + .../src/3.2.1/icon/list/index.html | 208 + .../src/3.2.1/icon/location-arrow/index.html | 208 + .../src/3.2.1/icon/lock/index.html | 208 + .../src/3.2.1/icon/long-arrow-down/index.html | 208 + .../src/3.2.1/icon/long-arrow-left/index.html | 208 + .../3.2.1/icon/long-arrow-right/index.html | 208 + .../src/3.2.1/icon/long-arrow-up/index.html | 208 + .../src/3.2.1/icon/magic/index.html | 208 + .../src/3.2.1/icon/magnet/index.html | 208 + .../src/3.2.1/icon/mail-reply-all/index.html | 208 + .../src/3.2.1/icon/male/index.html | 208 + .../src/3.2.1/icon/map-marker/index.html | 208 + .../src/3.2.1/icon/maxcdn/index.html | 208 + .../src/3.2.1/icon/medkit/index.html | 208 + .../src/3.2.1/icon/meh/index.html | 208 + .../src/3.2.1/icon/microphone-off/index.html | 208 + .../src/3.2.1/icon/microphone/index.html | 208 + .../src/3.2.1/icon/minus-sign-alt/index.html | 208 + .../src/3.2.1/icon/minus-sign/index.html | 208 + .../src/3.2.1/icon/minus/index.html | 208 + .../src/3.2.1/icon/mobile-phone/index.html | 208 + .../src/3.2.1/icon/money/index.html | 208 + .../src/3.2.1/icon/moon/index.html | 208 + .../src/3.2.1/icon/move/index.html | 208 + .../src/3.2.1/icon/music/index.html | 208 + .../src/3.2.1/icon/off/index.html | 213 + .../src/3.2.1/icon/ok-circle/index.html | 208 + .../src/3.2.1/icon/ok-sign/index.html | 208 + .../font-awesome/src/3.2.1/icon/ok/index.html | 208 + .../src/3.2.1/icon/paper-clip/index.html | 213 + .../src/3.2.1/icon/paste/index.html | 208 + .../src/3.2.1/icon/pause/index.html | 208 + .../src/3.2.1/icon/pencil/index.html | 208 + .../src/3.2.1/icon/phone-sign/index.html | 208 + .../src/3.2.1/icon/phone/index.html | 208 + .../src/3.2.1/icon/picture/index.html | 208 + .../src/3.2.1/icon/pinterest-sign/index.html | 208 + .../src/3.2.1/icon/pinterest/index.html | 208 + .../src/3.2.1/icon/plane/index.html | 208 + .../src/3.2.1/icon/play-circle/index.html | 208 + .../src/3.2.1/icon/play-sign/index.html | 208 + .../src/3.2.1/icon/play/index.html | 208 + .../src/3.2.1/icon/plus-sign-alt/index.html | 210 + .../src/3.2.1/icon/plus-sign/index.html | 208 + .../src/3.2.1/icon/plus/index.html | 208 + .../src/3.2.1/icon/print/index.html | 208 + .../src/3.2.1/icon/pushpin/index.html | 208 + .../src/3.2.1/icon/puzzle-piece/index.html | 208 + .../src/3.2.1/icon/qrcode/index.html | 208 + .../src/3.2.1/icon/question-sign/index.html | 208 + .../src/3.2.1/icon/question/index.html | 208 + .../src/3.2.1/icon/quote-left/index.html | 208 + .../src/3.2.1/icon/quote-right/index.html | 208 + .../src/3.2.1/icon/random/index.html | 208 + .../src/3.2.1/icon/refresh/index.html | 208 + .../src/3.2.1/icon/remove-circle/index.html | 208 + .../src/3.2.1/icon/remove-sign/index.html | 208 + .../src/3.2.1/icon/remove/index.html | 208 + .../src/3.2.1/icon/renren/index.html | 208 + .../src/3.2.1/icon/reorder/index.html | 208 + .../src/3.2.1/icon/repeat/index.html | 213 + .../src/3.2.1/icon/reply-all/index.html | 208 + .../src/3.2.1/icon/reply/index.html | 213 + .../src/3.2.1/icon/resize-full/index.html | 208 + .../3.2.1/icon/resize-horizontal/index.html | 208 + .../src/3.2.1/icon/resize-small/index.html | 208 + .../src/3.2.1/icon/resize-vertical/index.html | 208 + .../src/3.2.1/icon/retweet/index.html | 208 + .../src/3.2.1/icon/road/index.html | 208 + .../src/3.2.1/icon/rocket/index.html | 208 + .../src/3.2.1/icon/rss-sign/index.html | 208 + .../src/3.2.1/icon/rss/index.html | 208 + .../src/3.2.1/icon/save/index.html | 208 + .../src/3.2.1/icon/screenshot/index.html | 208 + .../src/3.2.1/icon/search/index.html | 208 + .../src/3.2.1/icon/share-alt/index.html | 213 + .../src/3.2.1/icon/share-sign/index.html | 208 + .../src/3.2.1/icon/share/index.html | 208 + .../src/3.2.1/icon/shield/index.html | 208 + .../src/3.2.1/icon/shopping-cart/index.html | 208 + .../src/3.2.1/icon/sign-blank/index.html | 208 + .../src/3.2.1/icon/signal/index.html | 208 + .../src/3.2.1/icon/signin/index.html | 208 + .../src/3.2.1/icon/signout/index.html | 208 + .../src/3.2.1/icon/sitemap/index.html | 208 + .../src/3.2.1/icon/skype/index.html | 208 + .../src/3.2.1/icon/smile/index.html | 208 + .../icon/sort-by-alphabet-alt/index.html | 208 + .../3.2.1/icon/sort-by-alphabet/index.html | 208 + .../icon/sort-by-attributes-alt/index.html | 208 + .../3.2.1/icon/sort-by-attributes/index.html | 208 + .../3.2.1/icon/sort-by-order-alt/index.html | 208 + .../src/3.2.1/icon/sort-by-order/index.html | 208 + .../src/3.2.1/icon/sort-down/index.html | 208 + .../src/3.2.1/icon/sort-up/index.html | 208 + .../src/3.2.1/icon/sort/index.html | 208 + .../src/3.2.1/icon/spinner/index.html | 208 + .../src/3.2.1/icon/stackexchange/index.html | 208 + .../src/3.2.1/icon/star-empty/index.html | 208 + .../src/3.2.1/icon/star-half-empty/index.html | 213 + .../src/3.2.1/icon/star-half/index.html | 208 + .../src/3.2.1/icon/star/index.html | 208 + .../src/3.2.1/icon/step-backward/index.html | 208 + .../src/3.2.1/icon/step-forward/index.html | 208 + .../src/3.2.1/icon/stethoscope/index.html | 208 + .../src/3.2.1/icon/stop/index.html | 208 + .../src/3.2.1/icon/strikethrough/index.html | 208 + .../src/3.2.1/icon/subscript/index.html | 208 + .../src/3.2.1/icon/suitcase/index.html | 208 + .../src/3.2.1/icon/sun/index.html | 208 + .../src/3.2.1/icon/superscript/index.html | 208 + .../src/3.2.1/icon/table/index.html | 208 + .../src/3.2.1/icon/tablet/index.html | 208 + .../src/3.2.1/icon/tag/index.html | 208 + .../src/3.2.1/icon/tags/index.html | 208 + .../src/3.2.1/icon/tasks/index.html | 208 + .../src/3.2.1/icon/terminal/index.html | 208 + .../src/3.2.1/icon/text-height/index.html | 208 + .../src/3.2.1/icon/text-width/index.html | 208 + .../src/3.2.1/icon/th-large/index.html | 208 + .../src/3.2.1/icon/th-list/index.html | 208 + .../font-awesome/src/3.2.1/icon/th/index.html | 208 + .../src/3.2.1/icon/thumbs-down-alt/index.html | 208 + .../src/3.2.1/icon/thumbs-down/index.html | 208 + .../src/3.2.1/icon/thumbs-up-alt/index.html | 208 + .../src/3.2.1/icon/thumbs-up/index.html | 208 + .../src/3.2.1/icon/ticket/index.html | 208 + .../src/3.2.1/icon/time/index.html | 208 + .../src/3.2.1/icon/tint/index.html | 208 + .../src/3.2.1/icon/trash/index.html | 208 + .../src/3.2.1/icon/trello/index.html | 208 + .../src/3.2.1/icon/trophy/index.html | 208 + .../src/3.2.1/icon/truck/index.html | 208 + .../src/3.2.1/icon/tumblr-sign/index.html | 208 + .../src/3.2.1/icon/tumblr/index.html | 208 + .../src/3.2.1/icon/twitter-sign/index.html | 208 + .../src/3.2.1/icon/twitter/index.html | 208 + .../src/3.2.1/icon/umbrella/index.html | 208 + .../src/3.2.1/icon/underline/index.html | 208 + .../src/3.2.1/icon/undo/index.html | 213 + .../src/3.2.1/icon/unlink/index.html | 208 + .../src/3.2.1/icon/unlock-alt/index.html | 208 + .../src/3.2.1/icon/unlock/index.html | 208 + .../src/3.2.1/icon/upload-alt/index.html | 208 + .../src/3.2.1/icon/upload/index.html | 208 + .../src/3.2.1/icon/usd/index.html | 213 + .../src/3.2.1/icon/user-md/index.html | 208 + .../src/3.2.1/icon/user/index.html | 208 + .../font-awesome/src/3.2.1/icon/vk/index.html | 208 + .../src/3.2.1/icon/volume-down/index.html | 208 + .../src/3.2.1/icon/volume-off/index.html | 208 + .../src/3.2.1/icon/volume-up/index.html | 208 + .../src/3.2.1/icon/warning-sign/index.html | 208 + .../src/3.2.1/icon/weibo/index.html | 208 + .../src/3.2.1/icon/windows/index.html | 208 + .../src/3.2.1/icon/wrench/index.html | 208 + .../src/3.2.1/icon/xing-sign/index.html | 208 + .../src/3.2.1/icon/xing/index.html | 208 + .../src/3.2.1/icon/youtube-play/index.html | 210 + .../src/3.2.1/icon/youtube-sign/index.html | 208 + .../src/3.2.1/icon/youtube/index.html | 208 + .../src/3.2.1/icon/zoom-in/index.html | 208 + .../src/3.2.1/icon/zoom-out/index.html | 208 + .../font-awesome/src/3.2.1/icons.yml | 2590 ++ .../font-awesome/src/3.2.1/icons/index.html | 1202 + .../font-awesome/src/3.2.1/index.html | 320 + .../font-awesome/src/3.2.1/license/index.html | 261 + .../font-awesome/src/3.2.1/test/index.html | 1056 + .../src/3.2.1/whats-new/index.html | 433 + dist/bower_components/font-awesome/src/CNAME | 1 + .../font-awesome/src/Makefile | 38 + .../_includes/ads/carbon-dark-vertical.html | 1 + .../ads/carbon-light-horizontal.html | 1 + .../_includes/ads/carbon-light-vertical.html | 1 + .../src/_includes/brand-license.html | 4 + .../_includes/community/getting-support.html | 22 + .../community/project-milestones.html | 7 + .../_includes/community/reporting-bugs.html | 18 + .../community/requesting-new-icons.html | 27 + .../community/submitting-pull-requests.html | 12 + .../src/_includes/examples/bootstrap.html | 93 + .../_includes/examples/bordered-pulled.html | 21 + .../src/_includes/examples/custom.html | 16 + .../src/_includes/examples/fixed-width.html | 27 + .../src/_includes/examples/inline.html | 17 + .../src/_includes/examples/larger.html | 29 + .../src/_includes/examples/list.html | 24 + .../_includes/examples/rotated-flipped.html | 28 + .../src/_includes/examples/spinning.html | 26 + .../src/_includes/examples/stacked.html | 59 + .../font-awesome/src/_includes/footer.html | 24 + .../src/_includes/icons/brand.html | 15 + .../src/_includes/icons/currency.html | 12 + .../src/_includes/icons/directional.html | 12 + .../src/_includes/icons/form-control.html | 11 + .../src/_includes/icons/medical.html | 12 + .../font-awesome/src/_includes/icons/new.html | 18 + .../src/_includes/icons/text-editor.html | 12 + .../src/_includes/icons/video-player.html | 12 + .../src/_includes/icons/web-application.html | 12 + .../src/_includes/jumbotron-carousel.html | 52 + .../font-awesome/src/_includes/jumbotron.html | 6 + .../src/_includes/license-code.less | 4 + .../font-awesome/src/_includes/navbar.html | 69 + .../src/_includes/new-features.html | 37 + .../src/_includes/new-naming.html | 157 + .../src/_includes/new-upgrading.html | 10 + .../font-awesome/src/_includes/stripe-ad.html | 6 + .../src/_includes/stripe-social.html | 18 + .../src/_includes/tell-me-thanks.html | 22 + .../tests/rotated-flipped-inside-anchor.html | 6 + .../tests/rotated-flipped-inside-btn.html | 6 + .../src/_includes/tests/rotated-flipped.html | 6 + .../tests/stacked-inside-anchor.html | 69 + .../src/_includes/tests/stacked.html | 58 + .../font-awesome/src/_includes/thanks-to.html | 26 + .../font-awesome/src/_includes/why.html | 41 + .../font-awesome/src/_layouts/base.html | 55 + .../font-awesome/src/_layouts/icon.html | 62 + .../src/_plugins/icon_page_generator.rb | 46 + .../font-awesome/src/_plugins/site.rb | 142 + .../font-awesome/src/assets/css/prettify.css | 30 + .../font-awesome/src/assets/css/pygments.css | 71 + .../assets/font-awesome/fonts/FontAwesome.otf | Bin 0 -> 62856 bytes .../fonts/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../fonts/fontawesome-webfont.svg | 414 + .../fonts/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../fonts/fontawesome-webfont.woff | Bin 0 -> 44432 bytes .../font-awesome/less/bordered-pulled.less | 19 + .../src/assets/font-awesome/less/core.less | 15 + .../assets/font-awesome/less/fixed-width.less | 9 + .../font-awesome/less/font-awesome.less | 16 + .../src/assets/font-awesome/less/icons.less | 7 + .../src/assets/font-awesome/less/larger.less | 16 + .../src/assets/font-awesome/less/list.less | 22 + .../src/assets/font-awesome/less/mixins.less | 22 + .../src/assets/font-awesome/less/path.less | 14 + .../font-awesome/less/rotated-flipped.less | 12 + .../assets/font-awesome/less/spinning.less | 33 + .../src/assets/font-awesome/less/stacked.less | 23 + .../assets/font-awesome/less/variables.less | 15 + .../font-awesome/scss/_bordered-pulled.scss | 19 + .../src/assets/font-awesome/scss/_core.scss | 15 + .../font-awesome/scss/_fixed-width.scss | 9 + .../src/assets/font-awesome/scss/_icons.scss | 7 + .../src/assets/font-awesome/scss/_larger.scss | 16 + .../src/assets/font-awesome/scss/_list.scss | 22 + .../src/assets/font-awesome/scss/_mixins.scss | 22 + .../src/assets/font-awesome/scss/_path.scss | 14 + .../font-awesome/scss/_rotated-flipped.scss | 12 + .../assets/font-awesome/scss/_spinning.scss | 33 + .../assets/font-awesome/scss/_stacked.scss | 23 + .../assets/font-awesome/scss/_variables.scss | 15 + .../font-awesome/scss/font-awesome.scss | 16 + .../font-awesome/src/assets/ico/favicon.ico | Bin 0 -> 1150 bytes .../src/assets/js/ZeroClipboard-1.1.7.min.js | 8 + .../src/assets/js/ZeroClipboard-1.1.7.swf | Bin 0 -> 1635 bytes .../src/assets/js/backbone.min.js | 37 + .../src/assets/js/bootstrap-2.3.1.min.js | 6 + .../src/assets/js/bootstrap-222.min.js | 6 + .../src/assets/js/bootstrap-3.0.0.min.js | 6 + .../font-awesome/src/assets/js/html5shiv.js | 8 + .../src/assets/js/jquery-1.10.2.js | 9789 +++++ .../src/assets/js/jquery-1.10.2.min.js | 6 + .../src/assets/js/jquery-1.10.2.min.map | 1 + .../src/assets/js/jquery-1.7.1.min.js | 4 + .../src/assets/js/prettify.min.js | 28 + .../font-awesome/src/assets/js/respond.min.js | 6 + .../font-awesome/src/assets/js/site.js | 38 + .../src/assets/js/underscore.min.js | 31 + .../assets/less/bootstrap-3.0.0/alerts.less | 67 + .../assets/less/bootstrap-3.0.0/badges.less | 51 + .../less/bootstrap-3.0.0/bootstrap.less | 59 + .../less/bootstrap-3.0.0/breadcrumbs.less | 23 + .../less/bootstrap-3.0.0/button-groups.less | 248 + .../assets/less/bootstrap-3.0.0/buttons.less | 160 + .../assets/less/bootstrap-3.0.0/carousel.less | 209 + .../assets/less/bootstrap-3.0.0/close.less | 33 + .../src/assets/less/bootstrap-3.0.0/code.less | 56 + .../bootstrap-3.0.0/component-animations.less | 29 + .../less/bootstrap-3.0.0/dropdowns.less | 193 + .../assets/less/bootstrap-3.0.0/forms.less | 353 + .../less/bootstrap-3.0.0/glyphicons.less | 232 + .../src/assets/less/bootstrap-3.0.0/grid.less | 346 + .../less/bootstrap-3.0.0/input-groups.less | 127 + .../less/bootstrap-3.0.0/jumbotron.less | 40 + .../assets/less/bootstrap-3.0.0/labels.less | 58 + .../less/bootstrap-3.0.0/list-group.less | 88 + .../assets/less/bootstrap-3.0.0/media.less | 56 + .../assets/less/bootstrap-3.0.0/mixins.less | 723 + .../assets/less/bootstrap-3.0.0/modals.less | 141 + .../assets/less/bootstrap-3.0.0/navbar.less | 621 + .../src/assets/less/bootstrap-3.0.0/navs.less | 229 + .../less/bootstrap-3.0.0/normalize.less | 396 + .../assets/less/bootstrap-3.0.0/pager.less | 55 + .../less/bootstrap-3.0.0/pagination.less | 83 + .../assets/less/bootstrap-3.0.0/panels.less | 148 + .../assets/less/bootstrap-3.0.0/popovers.less | 133 + .../assets/less/bootstrap-3.0.0/print.less | 100 + .../less/bootstrap-3.0.0/progress-bars.less | 95 + .../bootstrap-3.0.0/responsive-utilities.less | 220 + .../less/bootstrap-3.0.0/scaffolding.less | 130 + .../assets/less/bootstrap-3.0.0/tables.less | 236 + .../assets/less/bootstrap-3.0.0/theme.less | 232 + .../less/bootstrap-3.0.0/thumbnails.less | 31 + .../assets/less/bootstrap-3.0.0/tooltip.less | 95 + .../src/assets/less/bootstrap-3.0.0/type.less | 238 + .../less/bootstrap-3.0.0/utilities.less | 42 + .../less/bootstrap-3.0.0/variables.less | 620 + .../assets/less/bootstrap-3.0.0/wells.less | 29 + .../font-awesome/src/assets/less/site.less | 27 + .../assets/less/site/bootstrap/buttons.less | 3 + .../assets/less/site/bootstrap/jumbotron.less | 68 + .../assets/less/site/bootstrap/navbar.less | 33 + .../src/assets/less/site/bootstrap/type.less | 3 + .../assets/less/site/bootstrap/variables.less | 119 + .../src/assets/less/site/bootstrap/wells.less | 1 + .../src/assets/less/site/carbonad.less | 12 + .../src/assets/less/site/example-rating.less | 25 + .../src/assets/less/site/feature-list.less | 19 + .../less/site/fontawesome-icon-list.less | 32 + .../src/assets/less/site/footer.less | 40 + .../assets/less/site/jumbotron-carousel.less | 61 + .../src/assets/less/site/layout.less | 1 + .../src/assets/less/site/lazy.less | 86 + .../less/site/responsive/screen-lg.less | 53 + .../less/site/responsive/screen-md.less | 3 + .../less/site/responsive/screen-sm.less | 47 + .../less/site/responsive/screen-xs.less | 70 + .../src/assets/less/site/social-buttons.less | 9 + .../src/assets/less/site/stripe-ad.less | 7 + .../src/assets/less/site/textured-bg.less | 20 + .../font-awesome/src/cheatsheet.html | 32 + .../font-awesome/src/community.html | 34 + .../font-awesome/src/design.html | 1 + .../font-awesome/src/examples.html | 33 + .../font-awesome/src/get-started.html | 149 + .../font-awesome/src/glyphicons-test.html | 795 + .../font-awesome/src/icons.html | 33 + .../font-awesome/src/icons.yml | 2713 ++ .../font-awesome/src/index.html | 22 + .../font-awesome/src/license.html | 72 + .../font-awesome/src/test-2.3.2.html | 824 + .../font-awesome/src/test.html | 761 + .../font-awesome/src/whats-new.html | 18 + dist/bower_components/jcrop/.bower.json | 14 + dist/bower_components/jcrop/MIT-LICENSE.txt | 22 + dist/bower_components/jcrop/README.md | 66 + dist/bower_components/jcrop/css/Jcrop.gif | Bin 0 -> 329 bytes .../jcrop/css/jquery.Jcrop.css | 165 + .../jcrop/css/jquery.Jcrop.min.css | 29 + dist/bower_components/jcrop/demos/crop.php | 123 + .../jcrop/demos/demo_files/demos.css | 149 + .../jcrop/demos/demo_files/main.css | 4996 +++ .../jcrop/demos/demo_files/pool.jpg | Bin 0 -> 27637 bytes .../jcrop/demos/demo_files/sago.jpg | Bin 0 -> 18891 bytes .../jcrop/demos/demo_files/sagomod.jpg | Bin 0 -> 16251 bytes .../jcrop/demos/demo_files/sagomod.png | Bin 0 -> 78408 bytes .../jcrop/demos/non-image.html | 86 + .../bower_components/jcrop/demos/styling.html | 118 + .../jcrop/demos/tutorial1.html | 65 + .../jcrop/demos/tutorial2.html | 123 + .../jcrop/demos/tutorial3.html | 151 + .../jcrop/demos/tutorial4.html | 227 + .../jcrop/demos/tutorial5.html | 268 + dist/bower_components/jcrop/index.html | 84 + .../bower_components/jcrop/js/jquery.Jcrop.js | 1694 + .../jcrop/js/jquery.Jcrop.min.js | 22 + .../bower_components/jcrop/js/jquery.color.js | 661 + dist/bower_components/jcrop/js/jquery.min.js | 4 + dist/bower_components/jquery/.bower.json | 37 + dist/bower_components/jquery/MIT-LICENSE.txt | 21 + dist/bower_components/jquery/bower.json | 27 + dist/bower_components/jquery/dist/jquery.js | 9111 +++++ .../jquery/dist/jquery.min.js | 5 + .../jquery/dist/jquery.min.map | 1 + dist/bower_components/jquery/src/ajax.js | 806 + .../bower_components/jquery/src/ajax/jsonp.js | 89 + dist/bower_components/jquery/src/ajax/load.js | 75 + .../jquery/src/ajax/parseJSON.js | 13 + .../jquery/src/ajax/parseXML.js | 28 + .../jquery/src/ajax/script.js | 64 + .../jquery/src/ajax/var/nonce.js | 5 + .../jquery/src/ajax/var/rquery.js | 3 + dist/bower_components/jquery/src/ajax/xhr.js | 130 + .../bower_components/jquery/src/attributes.js | 11 + .../jquery/src/attributes/attr.js | 143 + .../jquery/src/attributes/classes.js | 158 + .../jquery/src/attributes/prop.js | 96 + .../jquery/src/attributes/support.js | 35 + .../jquery/src/attributes/val.js | 153 + dist/bower_components/jquery/src/callbacks.js | 205 + dist/bower_components/jquery/src/core.js | 500 + .../jquery/src/core/access.js | 60 + dist/bower_components/jquery/src/core/init.js | 123 + .../jquery/src/core/parseHTML.js | 39 + .../bower_components/jquery/src/core/ready.js | 96 + .../jquery/src/core/var/rsingleTag.js | 4 + dist/bower_components/jquery/src/css.js | 455 + .../jquery/src/css/addGetHookIf.js | 24 + .../bower_components/jquery/src/css/curCSS.js | 57 + .../jquery/src/css/defaultDisplay.js | 69 + .../jquery/src/css/hiddenVisibleSelectors.js | 15 + .../jquery/src/css/support.js | 83 + dist/bower_components/jquery/src/css/swap.js | 28 + .../jquery/src/css/var/cssExpand.js | 3 + .../jquery/src/css/var/getStyles.js | 5 + .../jquery/src/css/var/isHidden.js | 13 + .../jquery/src/css/var/rmargin.js | 3 + .../jquery/src/css/var/rnumnonpx.js | 5 + dist/bower_components/jquery/src/data.js | 175 + dist/bower_components/jquery/src/data/Data.js | 181 + .../jquery/src/data/accepts.js | 20 + .../jquery/src/data/var/data_priv.js | 5 + .../jquery/src/data/var/data_user.js | 5 + dist/bower_components/jquery/src/deferred.js | 149 + .../bower_components/jquery/src/deprecated.js | 13 + .../bower_components/jquery/src/dimensions.js | 50 + dist/bower_components/jquery/src/effects.js | 642 + .../jquery/src/effects/Tween.js | 114 + .../jquery/src/effects/animatedSelector.js | 13 + dist/bower_components/jquery/src/event.js | 859 + .../jquery/src/event/alias.js | 39 + .../jquery/src/event/support.js | 9 + .../jquery/src/exports/amd.js | 18 + .../jquery/src/exports/global.js | 32 + dist/bower_components/jquery/src/intro.js | 44 + dist/bower_components/jquery/src/jquery.js | 36 + .../jquery/src/manipulation.js | 583 + .../jquery/src/manipulation/_evalUrl.js | 18 + .../jquery/src/manipulation/support.js | 24 + .../src/manipulation/var/rcheckableType.js | 3 + dist/bower_components/jquery/src/offset.js | 204 + dist/bower_components/jquery/src/outro.js | 1 + dist/bower_components/jquery/src/queue.js | 142 + .../jquery/src/queue/delay.js | 22 + .../jquery/src/selector-native.js | 171 + .../jquery/src/selector-sizzle.js | 14 + dist/bower_components/jquery/src/selector.js | 1 + dist/bower_components/jquery/src/serialize.js | 111 + .../jquery/src/sizzle/dist/sizzle.js | 2015 + .../jquery/src/sizzle/dist/sizzle.min.js | 3 + .../jquery/src/sizzle/dist/sizzle.min.map | 1 + .../bower_components/jquery/src/traversing.js | 200 + .../jquery/src/traversing/findFilter.js | 100 + .../src/traversing/var/rneedsContext.js | 6 + dist/bower_components/jquery/src/var/arr.js | 3 + .../jquery/src/var/class2type.js | 4 + .../bower_components/jquery/src/var/concat.js | 5 + .../bower_components/jquery/src/var/hasOwn.js | 5 + .../jquery/src/var/indexOf.js | 5 + dist/bower_components/jquery/src/var/pnum.js | 3 + dist/bower_components/jquery/src/var/push.js | 5 + .../jquery/src/var/rnotwhite.js | 3 + dist/bower_components/jquery/src/var/slice.js | 5 + .../jquery/src/var/strundefined.js | 3 + .../jquery/src/var/support.js | 4 + .../jquery/src/var/toString.js | 5 + dist/bower_components/jquery/src/var/trim.js | 3 + dist/bower_components/jquery/src/wrap.js | 78 + dist/bower_components/json3/.bower.json | 31 + dist/bower_components/json3/LICENSE | 20 + dist/bower_components/json3/README.md | 126 + dist/bower_components/json3/bower.json | 21 + dist/bower_components/json3/lib/json3.js | 861 + dist/bower_components/json3/lib/json3.min.js | 18 + dist/bower_components/lodash/.bower.json | 33 + dist/bower_components/lodash/LICENSE.txt | 22 + dist/bower_components/lodash/bower.json | 23 + .../lodash/dist/lodash.compat.js | 7157 ++++ .../lodash/dist/lodash.compat.min.js | 61 + dist/bower_components/lodash/dist/lodash.js | 6785 ++++ .../lodash/dist/lodash.min.js | 56 + .../lodash/dist/lodash.underscore.js | 4979 +++ .../lodash/dist/lodash.underscore.min.js | 39 + dist/bower_components/moment/.bower.json | 30 + dist/bower_components/moment/LICENSE | 22 + dist/bower_components/moment/bower.json | 20 + dist/bower_components/moment/lang/ar-ma.js | 56 + dist/bower_components/moment/lang/ar.js | 56 + dist/bower_components/moment/lang/bg.js | 86 + dist/bower_components/moment/lang/br.js | 107 + dist/bower_components/moment/lang/bs.js | 139 + dist/bower_components/moment/lang/ca.js | 66 + dist/bower_components/moment/lang/cs.js | 155 + dist/bower_components/moment/lang/cv.js | 59 + dist/bower_components/moment/lang/cy.js | 77 + dist/bower_components/moment/lang/da.js | 56 + dist/bower_components/moment/lang/de.js | 71 + dist/bower_components/moment/lang/el.js | 79 + dist/bower_components/moment/lang/en-au.js | 62 + dist/bower_components/moment/lang/en-ca.js | 59 + dist/bower_components/moment/lang/en-gb.js | 63 + dist/bower_components/moment/lang/eo.js | 65 + dist/bower_components/moment/lang/es.js | 66 + dist/bower_components/moment/lang/et.js | 76 + dist/bower_components/moment/lang/eu.js | 60 + dist/bower_components/moment/lang/fa.js | 97 + dist/bower_components/moment/lang/fi.js | 103 + dist/bower_components/moment/lang/fo.js | 56 + dist/bower_components/moment/lang/fr-ca.js | 54 + dist/bower_components/moment/lang/fr.js | 58 + dist/bower_components/moment/lang/gl.js | 71 + dist/bower_components/moment/lang/he.js | 77 + dist/bower_components/moment/lang/hi.js | 105 + dist/bower_components/moment/lang/hr.js | 140 + dist/bower_components/moment/lang/hu.js | 98 + dist/bower_components/moment/lang/hy-am.js | 113 + dist/bower_components/moment/lang/id.js | 67 + dist/bower_components/moment/lang/is.js | 124 + dist/bower_components/moment/lang/it.js | 59 + dist/bower_components/moment/lang/ja.js | 58 + dist/bower_components/moment/lang/ka.js | 108 + dist/bower_components/moment/lang/ko.js | 63 + dist/bower_components/moment/lang/lb.js | 160 + dist/bower_components/moment/lang/lt.js | 118 + dist/bower_components/moment/lang/lv.js | 77 + dist/bower_components/moment/lang/mk.js | 86 + dist/bower_components/moment/lang/ml.js | 64 + dist/bower_components/moment/lang/mr.js | 104 + dist/bower_components/moment/lang/ms-my.js | 66 + dist/bower_components/moment/lang/nb.js | 57 + dist/bower_components/moment/lang/ne.js | 105 + dist/bower_components/moment/lang/nl.js | 67 + dist/bower_components/moment/lang/nn.js | 56 + dist/bower_components/moment/lang/pl.js | 98 + dist/bower_components/moment/lang/pt-br.js | 56 + dist/bower_components/moment/lang/pt.js | 60 + dist/bower_components/moment/lang/ro.js | 72 + dist/bower_components/moment/lang/rs.js | 139 + dist/bower_components/moment/lang/ru.js | 163 + dist/bower_components/moment/lang/sk.js | 156 + dist/bower_components/moment/lang/sl.js | 144 + dist/bower_components/moment/lang/sq.js | 57 + dist/bower_components/moment/lang/sv.js | 63 + dist/bower_components/moment/lang/ta.js | 112 + dist/bower_components/moment/lang/th.js | 58 + dist/bower_components/moment/lang/tl-ph.js | 58 + dist/bower_components/moment/lang/tr.js | 93 + dist/bower_components/moment/lang/tzm-la.js | 55 + dist/bower_components/moment/lang/tzm.js | 55 + dist/bower_components/moment/lang/uk.js | 157 + dist/bower_components/moment/lang/uz.js | 55 + dist/bower_components/moment/lang/vn.js | 62 + dist/bower_components/moment/lang/zh-cn.js | 108 + dist/bower_components/moment/lang/zh-tw.js | 84 + dist/bower_components/moment/min/langs.js | 5841 +++ dist/bower_components/moment/min/langs.min.js | 3 + .../moment/min/moment-with-langs.js | 7768 ++++ .../moment/min/moment-with-langs.min.js | 9 + .../bower_components/moment/min/moment.min.js | 6 + dist/bower_components/moment/moment.js | 2400 ++ dist/bower_components/moment/readme.md | 349 + dist/bower_components/nprogress/.bower.json | 32 + dist/bower_components/nprogress/History.md | 36 + dist/bower_components/nprogress/License.md | 19 + dist/bower_components/nprogress/Notes.md | 33 + dist/bower_components/nprogress/Readme.md | 147 + dist/bower_components/nprogress/bower.json | 24 + .../bower_components/nprogress/component.json | 22 + dist/bower_components/nprogress/index.html | 84 + dist/bower_components/nprogress/nprogress.css | 64 + dist/bower_components/nprogress/nprogress.js | 469 + dist/bower_components/nprogress/package.json | 18 + .../nprogress/support/extras.css | 4 + .../nprogress/support/style.css | 211 + .../nprogress/test/component.html | 26 + .../nprogress/test/index.html | 28 + dist/bower_components/nprogress/test/setup.js | 41 + .../nprogress/test/support/multisuite.js | 28 + dist/bower_components/nprogress/test/test.js | 150 + .../bower_components/nprogress/vendor/chai.js | 3996 ++ .../nprogress/vendor/jquery-1.10.js | 6 + .../nprogress/vendor/jquery-1.7.js | 4 + .../nprogress/vendor/jquery-1.8.js | 2 + .../nprogress/vendor/jquery-1.9.js | 5 + .../nprogress/vendor/jquery-2.0.js | 6 + .../nprogress/vendor/mocha.css | 231 + .../nprogress/vendor/mocha.js | 5340 +++ .../bower_components/onion-editor/.bower.json | 33 + .../onion-editor/Gruntfile.js | 69 + dist/bower_components/onion-editor/LICENSE | 20 + dist/bower_components/onion-editor/README.md | 6 + dist/bower_components/onion-editor/bower.json | 24 + .../onion-editor/build/onion-editor.js | 10124 +++++ .../onion-editor/build/onion-editor.min.js | 5 + .../onion-editor/package.json | 19 + dist/bower_components/raven-js/.bower.json | 16 + dist/bower_components/raven-js/.gitignore | 22 + dist/bower_components/raven-js/.jshintrc | 8 + dist/bower_components/raven-js/.travis.yml | 8 + dist/bower_components/raven-js/AUTHORS | 1 + dist/bower_components/raven-js/Gruntfile.js | 245 + dist/bower_components/raven-js/LICENSE | 9 + dist/bower_components/raven-js/Makefile | 20 + dist/bower_components/raven-js/README.md | 13 + dist/bower_components/raven-js/bower.json | 6 + dist/bower_components/raven-js/dist/raven.js | 1796 + .../raven-js/dist/raven.min.js | 3 + .../raven-js/dist/raven.min.map | 1 + dist/bower_components/raven-js/docs/Makefile | 153 + .../raven-js/docs/changelog/index.rst | 72 + dist/bower_components/raven-js/docs/conf.py | 244 + .../raven-js/docs/config/index.rst | 142 + .../raven-js/docs/contributing/index.rst | 92 + dist/bower_components/raven-js/docs/index.rst | 42 + .../raven-js/docs/install/index.rst | 47 + dist/bower_components/raven-js/docs/make.bat | 190 + .../raven-js/docs/plugins/index.rst | 20 + .../raven-js/docs/tips/index.rst | 64 + .../raven-js/docs/usage/index.rst | 117 + .../raven-js/example/Makefile | 3 + .../raven-js/example/file.min.js | 2 + .../raven-js/example/file.sourcemap.js | 1 + .../raven-js/example/file1.js | 4 + .../raven-js/example/file2.js | 12 + .../raven-js/example/index.html | 32 + .../raven-js/example/scratch.js | 38 + dist/bower_components/raven-js/package.json | 29 + .../raven-js/plugins/console.js | 36 + .../raven-js/plugins/jquery.js | 75 + .../raven-js/plugins/native.js | 33 + .../raven-js/plugins/require.js | 13 + dist/bower_components/raven-js/src/raven.js | 699 + .../raven-js/template/_copyright.js | 11 + .../raven-js/template/_footer.js | 9 + .../raven-js/template/_header.js | 2 + .../bower_components/raven-js/test/index.html | 62 + .../raven-js/test/raven.test.js | 1365 + .../raven-js/vendor/TraceKit/tracekit.js | 1072 + dist/bower_components/restangular/.bower.json | 29 + dist/bower_components/restangular/.gitignore | 17 + dist/bower_components/restangular/.travis.yml | 9 + .../bower_components/restangular/CHANGELOG.md | 160 + .../restangular/CONTRIBUTE.md | 17 + .../bower_components/restangular/Gruntfile.js | 164 + dist/bower_components/restangular/README.md | 1194 + dist/bower_components/restangular/bower.json | 19 + .../restangular/dist/restangular.js | 1305 + .../restangular/dist/restangular.min.js | 6 + .../restangular/dist/restangular.zip | Bin 0 -> 75378 bytes .../restangular/karma.conf.js | 74 + .../restangular/karma.underscore.conf.js | 74 + dist/bower_components/restangular/license.md | 21 + .../bower_components/restangular/package.json | 54 + .../restangular/src/restangular.js | 1300 + .../restangular/test/restangularSpec.js | 787 + dist/bower_components/underscore/.bower.json | 33 + .../bower_components/underscore/.editorconfig | 14 + dist/bower_components/underscore/.gitignore | 2 + dist/bower_components/underscore/LICENSE | 23 + dist/bower_components/underscore/README.md | 22 + dist/bower_components/underscore/bower.json | 8 + .../underscore/component.json | 10 + dist/bower_components/underscore/package.json | 27 + .../bower_components/underscore/underscore.js | 1343 + dist/bower_components/urlify/.bower.json | 13 + dist/bower_components/urlify/LICENSE | 27 + dist/bower_components/urlify/README.md | 2 + dist/bower_components/urlify/urlify.js | 163 + dist/favicon.ico | Bin 0 -> 4286 bytes dist/fonts/fontawesome-webfont.eot | Bin 0 -> 38205 bytes dist/fonts/fontawesome-webfont.svg | 414 + dist/fonts/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes dist/fonts/fontawesome-webfont.woff | Bin 0 -> 44432 bytes dist/fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20290 bytes dist/fonts/glyphicons-halflings-regular.svg | 229 + dist/fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41236 bytes dist/fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23292 bytes dist/images/loading.gif | Bin 0 -> 22490 bytes dist/images/onion.png | Bin 0 -> 14751 bytes dist/index.html | 182 + dist/robots.txt | 3 + dist/scripts/scripts.js | 2 + dist/scripts/templates.js | 2 + dist/scripts/vendor.js | 25 + dist/styles/Jcrop.gif | Bin 0 -> 329 bytes dist/styles/font-awesome.min.css | 4 + dist/styles/vendor.css | 5 + 1276 files changed, 343013 insertions(+), 1 deletion(-) create mode 100644 dist/.htaccess create mode 100644 dist/404.html create mode 100644 dist/bower_components/angular-bootstrap-datetimepicker/.bower.json create mode 100644 dist/bower_components/angular-bootstrap-datetimepicker/LICENSE create mode 100644 dist/bower_components/angular-bootstrap-datetimepicker/README.md create mode 100644 dist/bower_components/angular-bootstrap-datetimepicker/bower.json create mode 100644 dist/bower_components/angular-bootstrap-datetimepicker/karma.conf.js create mode 100644 dist/bower_components/angular-bootstrap-datetimepicker/src/css/datetimepicker.css create mode 100644 dist/bower_components/angular-bootstrap-datetimepicker/src/js/datetimepicker.js create mode 100644 dist/bower_components/angular-bootstrap/.bower.json create mode 100644 dist/bower_components/angular-bootstrap/bower.json create mode 100644 dist/bower_components/angular-bootstrap/ui-bootstrap-tpls.js create mode 100644 dist/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js create mode 100644 dist/bower_components/angular-bootstrap/ui-bootstrap.js create mode 100644 dist/bower_components/angular-bootstrap/ui-bootstrap.min.js create mode 100644 dist/bower_components/angular-cookies/.bower.json create mode 100644 dist/bower_components/angular-cookies/README.md create mode 100644 dist/bower_components/angular-cookies/angular-cookies.js create mode 100644 dist/bower_components/angular-cookies/angular-cookies.min.js create mode 100644 dist/bower_components/angular-cookies/angular-cookies.min.js.map create mode 100644 dist/bower_components/angular-cookies/bower.json create mode 100644 dist/bower_components/angular-mocks/.bower.json create mode 100644 dist/bower_components/angular-mocks/README.md create mode 100644 dist/bower_components/angular-mocks/angular-mocks.js create mode 100644 dist/bower_components/angular-mocks/bower.json create mode 100644 dist/bower_components/angular-resource/.bower.json create mode 100644 dist/bower_components/angular-resource/README.md create mode 100644 dist/bower_components/angular-resource/angular-resource.js create mode 100644 dist/bower_components/angular-resource/angular-resource.min.js create mode 100644 dist/bower_components/angular-resource/angular-resource.min.js.map create mode 100644 dist/bower_components/angular-resource/bower.json create mode 100644 dist/bower_components/angular-route/.bower.json create mode 100644 dist/bower_components/angular-route/README.md create mode 100644 dist/bower_components/angular-route/angular-route.js create mode 100644 dist/bower_components/angular-route/angular-route.min.js create mode 100644 dist/bower_components/angular-route/angular-route.min.js.map create mode 100644 dist/bower_components/angular-route/bower.json create mode 100644 dist/bower_components/angular-sanitize/.bower.json create mode 100644 dist/bower_components/angular-sanitize/README.md create mode 100644 dist/bower_components/angular-sanitize/angular-sanitize.js create mode 100644 dist/bower_components/angular-sanitize/angular-sanitize.min.js create mode 100644 dist/bower_components/angular-sanitize/angular-sanitize.min.js.map create mode 100644 dist/bower_components/angular-sanitize/bower.json create mode 100644 dist/bower_components/angular-scenario/.bower.json create mode 100644 dist/bower_components/angular-scenario/README.md create mode 100644 dist/bower_components/angular-scenario/angular-scenario.js create mode 100644 dist/bower_components/angular-scenario/bower.json create mode 100644 dist/bower_components/angular-scenario/jstd-scenario-adapter-config.js create mode 100644 dist/bower_components/angular-scenario/jstd-scenario-adapter.js create mode 100644 dist/bower_components/angular/.bower.json create mode 100644 dist/bower_components/angular/README.md create mode 100644 dist/bower_components/angular/angular-csp.css create mode 100644 dist/bower_components/angular/angular.js create mode 100644 dist/bower_components/angular/angular.min.js create mode 100644 dist/bower_components/angular/angular.min.js.gzip create mode 100644 dist/bower_components/angular/angular.min.js.map create mode 100644 dist/bower_components/angular/bower.json create mode 100644 dist/bower_components/bootstrap-datetimepicker/.bower.json create mode 100644 dist/bower_components/bootstrap-datetimepicker/.gitignore create mode 100644 dist/bower_components/bootstrap-datetimepicker/.gitmodules create mode 100644 dist/bower_components/bootstrap-datetimepicker/.lvimrc create mode 100644 dist/bower_components/bootstrap-datetimepicker/.npmignore create mode 100644 dist/bower_components/bootstrap-datetimepicker/CONTRIBUTING.md create mode 100644 dist/bower_components/bootstrap-datetimepicker/LICENSE create mode 100644 dist/bower_components/bootstrap-datetimepicker/Makefile create mode 100644 dist/bower_components/bootstrap-datetimepicker/README.md create mode 100644 dist/bower_components/bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css create mode 100644 dist/bower_components/bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/component.json create mode 100644 dist/bower_components/bootstrap-datetimepicker/package.json create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/bootstrap-datetimepicker.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.bg.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.cs.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.da.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.de.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.es.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.fa-IR.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.fi.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.fo.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.fr.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.hr.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.hu.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.id.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.is.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.it.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.ja.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.kr.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.lt.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.lv.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.ms.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.nb.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.nl.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.pl.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.pt-BR.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.pt.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.ro.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.rs-latin.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.rs.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.ru.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.sk.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.sl.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.sv.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.th.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.tr.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.zh-CN.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/js/locales/bootstrap-datetimepicker.zh-TW.js create mode 100644 dist/bower_components/bootstrap-datetimepicker/src/less/bootstrap-datetimepicker.less create mode 100644 dist/bower_components/bootstrap-datetimepicker/test/basic-test-cases/TEMPLATE/template.html create mode 100644 dist/bower_components/bootstrap-datetimepicker/test/basic-test-cases/no-collapsible/index.html create mode 100644 dist/bower_components/bootstrap-datetimepicker/test/issues.coffee create mode 100644 dist/bower_components/bootstrap-datetimepicker/test/run.sh create mode 100644 dist/bower_components/bootstrap-datetimepicker/test/specs.coffee create mode 100644 dist/bower_components/bootstrap-datetimepicker/test/test.html create mode 100644 dist/bower_components/bootstrap-datetimepicker/test/utils.coffee create mode 100644 dist/bower_components/bootstrap-switch/.bower.json create mode 100644 dist/bower_components/bootstrap-switch/.gitignore create mode 100644 dist/bower_components/bootstrap-switch/CNAME create mode 100644 dist/bower_components/bootstrap-switch/CONTRIBUTING.md create mode 100644 dist/bower_components/bootstrap-switch/Gruntfile.coffee create mode 100644 dist/bower_components/bootstrap-switch/LICENSE create mode 100644 dist/bower_components/bootstrap-switch/README.md create mode 100644 dist/bower_components/bootstrap-switch/bower.json create mode 100644 dist/bower_components/bootstrap-switch/build/css/bootstrap2/bootstrap-switch.css create mode 100644 dist/bower_components/bootstrap-switch/build/css/bootstrap2/bootstrap-switch.min.css create mode 100644 dist/bower_components/bootstrap-switch/build/css/bootstrap3/bootstrap-switch.css create mode 100644 dist/bower_components/bootstrap-switch/build/css/bootstrap3/bootstrap-switch.min.css create mode 100644 dist/bower_components/bootstrap-switch/build/js/bootstrap-switch.js create mode 100644 dist/bower_components/bootstrap-switch/build/js/bootstrap-switch.min.js create mode 100644 dist/bower_components/bootstrap-switch/composer.json create mode 100644 dist/bower_components/bootstrap-switch/index.html create mode 100644 dist/bower_components/bootstrap-switch/package.json create mode 100644 dist/bower_components/bootstrap-switch/src/coffee/bootstrap-switch.coffee create mode 100644 dist/bower_components/bootstrap-switch/src/less/bootstrap2/bootstrap-switch.less create mode 100644 dist/bower_components/bootstrap-switch/src/less/bootstrap2/mixins.less create mode 100644 dist/bower_components/bootstrap-switch/src/less/bootstrap2/variables.less create mode 100644 dist/bower_components/bootstrap-switch/src/less/bootstrap3/bootstrap-switch.less create mode 100644 dist/bower_components/bootstrap-switch/src/less/bootstrap3/mixins.less create mode 100644 dist/bower_components/bootstrap-switch/src/less/bootstrap3/variables.less create mode 100644 dist/bower_components/bootstrap/.bower.json create mode 100644 dist/bower_components/bootstrap/Gruntfile.js create mode 100644 dist/bower_components/bootstrap/LICENSE create mode 100644 dist/bower_components/bootstrap/README.md create mode 100644 dist/bower_components/bootstrap/bower.json create mode 100644 dist/bower_components/bootstrap/browserstack.json create mode 100644 dist/bower_components/bootstrap/dist/css/bootstrap-theme.css create mode 100644 dist/bower_components/bootstrap/dist/css/bootstrap-theme.css.map create mode 100644 dist/bower_components/bootstrap/dist/css/bootstrap-theme.min.css create mode 100644 dist/bower_components/bootstrap/dist/css/bootstrap.css create mode 100644 dist/bower_components/bootstrap/dist/css/bootstrap.css.map create mode 100644 dist/bower_components/bootstrap/dist/css/bootstrap.min.css create mode 100644 dist/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot create mode 100644 dist/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg create mode 100644 dist/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf create mode 100644 dist/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff create mode 100644 dist/bower_components/bootstrap/dist/js/bootstrap.js create mode 100644 dist/bower_components/bootstrap/dist/js/bootstrap.min.js create mode 100644 dist/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 dist/bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 dist/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 dist/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 dist/bower_components/bootstrap/js/affix.js create mode 100644 dist/bower_components/bootstrap/js/alert.js create mode 100644 dist/bower_components/bootstrap/js/button.js create mode 100644 dist/bower_components/bootstrap/js/carousel.js create mode 100644 dist/bower_components/bootstrap/js/collapse.js create mode 100644 dist/bower_components/bootstrap/js/dropdown.js create mode 100644 dist/bower_components/bootstrap/js/modal.js create mode 100644 dist/bower_components/bootstrap/js/popover.js create mode 100644 dist/bower_components/bootstrap/js/scrollspy.js create mode 100644 dist/bower_components/bootstrap/js/tab.js create mode 100644 dist/bower_components/bootstrap/js/tooltip.js create mode 100644 dist/bower_components/bootstrap/js/transition.js create mode 100644 dist/bower_components/bootstrap/less/alerts.less create mode 100644 dist/bower_components/bootstrap/less/badges.less create mode 100644 dist/bower_components/bootstrap/less/bootstrap.less create mode 100644 dist/bower_components/bootstrap/less/breadcrumbs.less create mode 100644 dist/bower_components/bootstrap/less/button-groups.less create mode 100644 dist/bower_components/bootstrap/less/buttons.less create mode 100644 dist/bower_components/bootstrap/less/carousel.less create mode 100644 dist/bower_components/bootstrap/less/close.less create mode 100644 dist/bower_components/bootstrap/less/code.less create mode 100644 dist/bower_components/bootstrap/less/component-animations.less create mode 100644 dist/bower_components/bootstrap/less/dropdowns.less create mode 100644 dist/bower_components/bootstrap/less/forms.less create mode 100644 dist/bower_components/bootstrap/less/glyphicons.less create mode 100644 dist/bower_components/bootstrap/less/grid.less create mode 100644 dist/bower_components/bootstrap/less/input-groups.less create mode 100644 dist/bower_components/bootstrap/less/jumbotron.less create mode 100644 dist/bower_components/bootstrap/less/labels.less create mode 100644 dist/bower_components/bootstrap/less/list-group.less create mode 100644 dist/bower_components/bootstrap/less/media.less create mode 100644 dist/bower_components/bootstrap/less/mixins.less create mode 100644 dist/bower_components/bootstrap/less/modals.less create mode 100644 dist/bower_components/bootstrap/less/navbar.less create mode 100644 dist/bower_components/bootstrap/less/navs.less create mode 100644 dist/bower_components/bootstrap/less/normalize.less create mode 100644 dist/bower_components/bootstrap/less/pager.less create mode 100644 dist/bower_components/bootstrap/less/pagination.less create mode 100644 dist/bower_components/bootstrap/less/panels.less create mode 100644 dist/bower_components/bootstrap/less/popovers.less create mode 100644 dist/bower_components/bootstrap/less/print.less create mode 100644 dist/bower_components/bootstrap/less/progress-bars.less create mode 100644 dist/bower_components/bootstrap/less/responsive-utilities.less create mode 100644 dist/bower_components/bootstrap/less/scaffolding.less create mode 100644 dist/bower_components/bootstrap/less/tables.less create mode 100644 dist/bower_components/bootstrap/less/theme.less create mode 100644 dist/bower_components/bootstrap/less/thumbnails.less create mode 100644 dist/bower_components/bootstrap/less/tooltip.less create mode 100644 dist/bower_components/bootstrap/less/type.less create mode 100644 dist/bower_components/bootstrap/less/utilities.less create mode 100644 dist/bower_components/bootstrap/less/variables.less create mode 100644 dist/bower_components/bootstrap/less/wells.less create mode 100644 dist/bower_components/bootstrap/package.json create mode 100644 dist/bower_components/bootstrap/test-infra/README.md create mode 100644 dist/bower_components/bootstrap/test-infra/npm-shrinkwrap.canonical.json create mode 100644 dist/bower_components/bootstrap/test-infra/requirements.txt create mode 100644 dist/bower_components/bootstrap/test-infra/s3_cache.py create mode 100644 dist/bower_components/bootstrap/test-infra/sauce_browsers.yml create mode 100644 dist/bower_components/bootstrap/test-infra/shrinkwrap.js create mode 100644 dist/bower_components/bootstrap/test-infra/uncached-npm-install.sh create mode 100644 dist/bower_components/es5-shim/.bower.json create mode 100644 dist/bower_components/es5-shim/.gitignore create mode 100644 dist/bower_components/es5-shim/CHANGES create mode 100644 dist/bower_components/es5-shim/CONTRIBUTORS.md create mode 100644 dist/bower_components/es5-shim/LICENSE create mode 100644 dist/bower_components/es5-shim/README.md create mode 100644 dist/bower_components/es5-shim/es5-sham.js create mode 100644 dist/bower_components/es5-shim/es5-sham.map create mode 100644 dist/bower_components/es5-shim/es5-sham.min.js create mode 100644 dist/bower_components/es5-shim/es5-shim.js create mode 100644 dist/bower_components/es5-shim/es5-shim.map create mode 100644 dist/bower_components/es5-shim/es5-shim.min.js create mode 100644 dist/bower_components/es5-shim/package.json create mode 100644 dist/bower_components/es5-shim/tests/helpers/h-kill.js create mode 100644 dist/bower_components/es5-shim/tests/helpers/h-matchers.js create mode 100644 dist/bower_components/es5-shim/tests/helpers/h.js create mode 100644 dist/bower_components/es5-shim/tests/index.html create mode 100644 dist/bower_components/es5-shim/tests/index.min.html create mode 100644 dist/bower_components/es5-shim/tests/lib/jasmine-html.js create mode 100644 dist/bower_components/es5-shim/tests/lib/jasmine.css create mode 100644 dist/bower_components/es5-shim/tests/lib/jasmine.js create mode 100644 dist/bower_components/es5-shim/tests/lib/jasmine_favicon.png create mode 100644 dist/bower_components/es5-shim/tests/lib/json2.js create mode 100644 dist/bower_components/es5-shim/tests/spec/s-array.js create mode 100644 dist/bower_components/es5-shim/tests/spec/s-date.js create mode 100644 dist/bower_components/es5-shim/tests/spec/s-function.js create mode 100644 dist/bower_components/es5-shim/tests/spec/s-number.js create mode 100644 dist/bower_components/es5-shim/tests/spec/s-object.js create mode 100644 dist/bower_components/es5-shim/tests/spec/s-string.js create mode 100644 dist/bower_components/font-awesome/.bower.json create mode 100644 dist/bower_components/font-awesome/.gitignore create mode 100644 dist/bower_components/font-awesome/CONTRIBUTING.md create mode 100644 dist/bower_components/font-awesome/Gemfile create mode 100644 dist/bower_components/font-awesome/Gemfile.lock create mode 100644 dist/bower_components/font-awesome/README.md create mode 100644 dist/bower_components/font-awesome/_config.yml create mode 100644 dist/bower_components/font-awesome/component.json create mode 100644 dist/bower_components/font-awesome/composer.json create mode 100644 dist/bower_components/font-awesome/css/font-awesome.css create mode 100644 dist/bower_components/font-awesome/css/font-awesome.min.css create mode 100644 dist/bower_components/font-awesome/fonts/FontAwesome.otf create mode 100644 dist/bower_components/font-awesome/fonts/fontawesome-webfont.eot create mode 100644 dist/bower_components/font-awesome/fonts/fontawesome-webfont.svg create mode 100644 dist/bower_components/font-awesome/fonts/fontawesome-webfont.ttf create mode 100644 dist/bower_components/font-awesome/fonts/fontawesome-webfont.woff create mode 100644 dist/bower_components/font-awesome/less/bordered-pulled.less create mode 100644 dist/bower_components/font-awesome/less/core.less create mode 100644 dist/bower_components/font-awesome/less/extras.less create mode 100644 dist/bower_components/font-awesome/less/fixed-width.less create mode 100644 dist/bower_components/font-awesome/less/font-awesome.less create mode 100644 dist/bower_components/font-awesome/less/icons.less create mode 100644 dist/bower_components/font-awesome/less/larger.less create mode 100644 dist/bower_components/font-awesome/less/list.less create mode 100644 dist/bower_components/font-awesome/less/mixins.less create mode 100644 dist/bower_components/font-awesome/less/path.less create mode 100644 dist/bower_components/font-awesome/less/rotated-flipped.less create mode 100644 dist/bower_components/font-awesome/less/spinning.less create mode 100644 dist/bower_components/font-awesome/less/stacked.less create mode 100644 dist/bower_components/font-awesome/less/variables.less create mode 100644 dist/bower_components/font-awesome/package.json create mode 100644 dist/bower_components/font-awesome/scss/_bordered-pulled.scss create mode 100644 dist/bower_components/font-awesome/scss/_core.scss create mode 100644 dist/bower_components/font-awesome/scss/_extras.scss create mode 100644 dist/bower_components/font-awesome/scss/_fixed-width.scss create mode 100644 dist/bower_components/font-awesome/scss/_icons.scss create mode 100644 dist/bower_components/font-awesome/scss/_larger.scss create mode 100644 dist/bower_components/font-awesome/scss/_list.scss create mode 100644 dist/bower_components/font-awesome/scss/_mixins.scss create mode 100644 dist/bower_components/font-awesome/scss/_path.scss create mode 100644 dist/bower_components/font-awesome/scss/_rotated-flipped.scss create mode 100644 dist/bower_components/font-awesome/scss/_spinning.scss create mode 100644 dist/bower_components/font-awesome/scss/_stacked.scss create mode 100644 dist/bower_components/font-awesome/scss/_variables.scss create mode 100644 dist/bower_components/font-awesome/scss/font-awesome.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/CNAME create mode 100644 dist/bower_components/font-awesome/src/3.2.1/Makefile create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/css/prettify.css create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/css/pygments.css create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/css/site.css create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome.zip create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/css/font-awesome-ie7.css create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/css/font-awesome-ie7.min.css create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/css/font-awesome.css create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/css/font-awesome.min.css create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/font/FontAwesome.otf create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/font/fontawesome-webfont.eot create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/font/fontawesome-webfont.svg create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/font/fontawesome-webfont.ttf create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/font/fontawesome-webfont.woff create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/less/bootstrap.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/less/core.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/less/extras.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/less/font-awesome-ie7.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/less/font-awesome.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/less/icons.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/less/mixins.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/less/path.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/less/variables.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/scss/_bootstrap.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/scss/_core.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/scss/_extras.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/scss/_icons.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/scss/_mixins.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/scss/_path.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/scss/_variables.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/scss/font-awesome-ie7.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/font-awesome/scss/font-awesome.scss create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/ico/favicon.ico create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/img/contribution-sample.png create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/img/fort_awesome.jpg create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/img/glyphicons-halflings-white.png create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/img/glyphicons-halflings.png create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/img/icon-flag.pdf create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/js/ZeroClipboard-1.1.7.min.js create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/js/ZeroClipboard-1.1.7.swf create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/js/backbone.min.js create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/js/bootstrap-2.3.1.min.js create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/js/bootstrap-222.min.js create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/js/jquery-1.7.1.min.js create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/js/prettify.min.js create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/js/site.js create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/js/underscore.min.js create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/accordion.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/alerts.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/bootstrap.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/breadcrumbs.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/button-groups.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/buttons.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/carousel.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/close.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/code.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/component-animations.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/dropdowns.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/forms.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/grid.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/hero-unit.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/labels-badges.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/layouts.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/media.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/mixins.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/modals.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/navbar.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/navs.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/pager.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/pagination.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/popovers.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/progress-bars.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/reset.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/responsive-1200px-min.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/responsive-767px-max.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/responsive-768px-979px.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/responsive-navbar.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/responsive-utilities.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/responsive.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/scaffolding.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/sprites.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/tables.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/thumbnails.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/tooltip.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/type.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/utilities.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/variables.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/bootstrap-2.3.2/wells.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/lazy.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/mixins.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/responsive-1200px-min.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/responsive-767px-max.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/responsive-768px-979px.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/responsive-navbar.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/responsive.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/site.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/sticky-footer.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/assets/less/variables.less create mode 100644 dist/bower_components/font-awesome/src/3.2.1/cheatsheet/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/community/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/design.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/examples/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/get-started/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/adjust/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/adn/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/align-center/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/align-justify/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/align-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/align-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/ambulance/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/anchor/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/android/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/angle-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/angle-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/angle-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/angle-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/apple/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/archive/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/arrow-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/arrow-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/arrow-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/arrow-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/asterisk/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/backward/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/ban-circle/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bar-chart/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/barcode/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/beaker/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/beer/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bell-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bell/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bitbucket-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bitbucket/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bold/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bolt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/book/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bookmark-empty/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bookmark/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/briefcase/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/btc/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bug/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/building/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bullhorn/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/bullseye/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/calendar-empty/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/calendar/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/camera-retro/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/camera/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/caret-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/caret-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/caret-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/caret-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/certificate/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/check-empty/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/check-minus/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/check-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/check/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/chevron-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/chevron-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/chevron-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/chevron-sign-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/chevron-sign-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/chevron-sign-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/chevron-sign-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/chevron-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/circle-arrow-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/circle-arrow-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/circle-arrow-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/circle-arrow-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/circle-blank/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/circle/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/cloud-download/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/cloud-upload/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/cloud/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/cny/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/code-fork/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/code/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/coffee/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/cog/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/cogs/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/collapse-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/collapse-top/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/collapse/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/columns/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/comment-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/comment/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/comments-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/comments/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/compass/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/copy/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/credit-card/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/crop/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/css3/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/cut/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/dashboard/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/desktop/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/double-angle-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/double-angle-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/double-angle-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/double-angle-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/download-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/download/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/dribbble/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/dropbox/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/edit-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/edit/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/eject/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/ellipsis-horizontal/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/ellipsis-vertical/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/envelope-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/envelope/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/eraser/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/eur/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/exchange/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/exclamation-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/exclamation/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/expand-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/expand/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/external-link-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/external-link/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/eye-close/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/eye-open/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/facebook-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/facebook/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/facetime-video/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/fast-backward/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/fast-forward/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/female/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/fighter-jet/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/file-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/file-text-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/file-text/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/file/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/film/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/filter/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/fire-extinguisher/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/fire/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/flag-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/flag-checkered/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/flag/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/flickr/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/folder-close-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/folder-close/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/folder-open-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/folder-open/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/font/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/food/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/forward/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/foursquare/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/frown/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/fullscreen/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/gamepad/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/gbp/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/gift/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/github-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/github-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/github/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/gittip/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/glass/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/globe/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/google-plus-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/google-plus/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/group/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/h-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/hand-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/hand-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/hand-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/hand-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/hdd/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/headphones/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/heart-empty/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/heart/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/home/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/hospital/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/html5/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/inbox/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/indent-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/indent-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/info-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/info/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/inr/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/instagram/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/italic/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/jpy/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/key/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/keyboard/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/krw/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/laptop/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/leaf/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/legal/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/lemon/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/level-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/level-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/lightbulb/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/link/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/linkedin-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/linkedin/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/linux/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/list-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/list-ol/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/list-ul/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/list/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/location-arrow/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/lock/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/long-arrow-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/long-arrow-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/long-arrow-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/long-arrow-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/magic/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/magnet/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/mail-reply-all/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/male/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/map-marker/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/maxcdn/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/medkit/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/meh/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/microphone-off/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/microphone/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/minus-sign-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/minus-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/minus/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/mobile-phone/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/money/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/moon/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/move/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/music/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/off/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/ok-circle/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/ok-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/ok/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/paper-clip/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/paste/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/pause/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/pencil/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/phone-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/phone/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/picture/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/pinterest-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/pinterest/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/plane/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/play-circle/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/play-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/play/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/plus-sign-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/plus-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/plus/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/print/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/pushpin/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/puzzle-piece/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/qrcode/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/question-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/question/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/quote-left/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/quote-right/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/random/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/refresh/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/remove-circle/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/remove-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/remove/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/renren/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/reorder/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/repeat/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/reply-all/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/reply/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/resize-full/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/resize-horizontal/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/resize-small/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/resize-vertical/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/retweet/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/road/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/rocket/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/rss-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/rss/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/save/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/screenshot/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/search/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/share-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/share-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/share/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/shield/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/shopping-cart/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sign-blank/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/signal/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/signin/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/signout/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sitemap/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/skype/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/smile/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sort-by-alphabet-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sort-by-alphabet/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sort-by-attributes-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sort-by-attributes/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sort-by-order-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sort-by-order/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sort-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sort-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sort/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/spinner/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/stackexchange/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/star-empty/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/star-half-empty/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/star-half/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/star/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/step-backward/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/step-forward/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/stethoscope/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/stop/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/strikethrough/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/subscript/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/suitcase/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/sun/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/superscript/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/table/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/tablet/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/tag/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/tags/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/tasks/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/terminal/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/text-height/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/text-width/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/th-large/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/th-list/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/th/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/thumbs-down-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/thumbs-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/thumbs-up-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/thumbs-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/ticket/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/time/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/tint/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/trash/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/trello/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/trophy/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/truck/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/tumblr-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/tumblr/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/twitter-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/twitter/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/umbrella/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/underline/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/undo/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/unlink/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/unlock-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/unlock/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/upload-alt/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/upload/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/usd/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/user-md/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/user/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/vk/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/volume-down/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/volume-off/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/volume-up/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/warning-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/weibo/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/windows/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/wrench/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/xing-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/xing/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/youtube-play/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/youtube-sign/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/youtube/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/zoom-in/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icon/zoom-out/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icons.yml create mode 100644 dist/bower_components/font-awesome/src/3.2.1/icons/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/license/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/test/index.html create mode 100644 dist/bower_components/font-awesome/src/3.2.1/whats-new/index.html create mode 100644 dist/bower_components/font-awesome/src/CNAME create mode 100644 dist/bower_components/font-awesome/src/Makefile create mode 100644 dist/bower_components/font-awesome/src/_includes/ads/carbon-dark-vertical.html create mode 100644 dist/bower_components/font-awesome/src/_includes/ads/carbon-light-horizontal.html create mode 100644 dist/bower_components/font-awesome/src/_includes/ads/carbon-light-vertical.html create mode 100644 dist/bower_components/font-awesome/src/_includes/brand-license.html create mode 100644 dist/bower_components/font-awesome/src/_includes/community/getting-support.html create mode 100644 dist/bower_components/font-awesome/src/_includes/community/project-milestones.html create mode 100644 dist/bower_components/font-awesome/src/_includes/community/reporting-bugs.html create mode 100644 dist/bower_components/font-awesome/src/_includes/community/requesting-new-icons.html create mode 100644 dist/bower_components/font-awesome/src/_includes/community/submitting-pull-requests.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/bootstrap.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/bordered-pulled.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/custom.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/fixed-width.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/inline.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/larger.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/list.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/rotated-flipped.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/spinning.html create mode 100644 dist/bower_components/font-awesome/src/_includes/examples/stacked.html create mode 100644 dist/bower_components/font-awesome/src/_includes/footer.html create mode 100644 dist/bower_components/font-awesome/src/_includes/icons/brand.html create mode 100644 dist/bower_components/font-awesome/src/_includes/icons/currency.html create mode 100644 dist/bower_components/font-awesome/src/_includes/icons/directional.html create mode 100644 dist/bower_components/font-awesome/src/_includes/icons/form-control.html create mode 100644 dist/bower_components/font-awesome/src/_includes/icons/medical.html create mode 100644 dist/bower_components/font-awesome/src/_includes/icons/new.html create mode 100644 dist/bower_components/font-awesome/src/_includes/icons/text-editor.html create mode 100644 dist/bower_components/font-awesome/src/_includes/icons/video-player.html create mode 100644 dist/bower_components/font-awesome/src/_includes/icons/web-application.html create mode 100644 dist/bower_components/font-awesome/src/_includes/jumbotron-carousel.html create mode 100644 dist/bower_components/font-awesome/src/_includes/jumbotron.html create mode 100644 dist/bower_components/font-awesome/src/_includes/license-code.less create mode 100644 dist/bower_components/font-awesome/src/_includes/navbar.html create mode 100644 dist/bower_components/font-awesome/src/_includes/new-features.html create mode 100644 dist/bower_components/font-awesome/src/_includes/new-naming.html create mode 100644 dist/bower_components/font-awesome/src/_includes/new-upgrading.html create mode 100644 dist/bower_components/font-awesome/src/_includes/stripe-ad.html create mode 100644 dist/bower_components/font-awesome/src/_includes/stripe-social.html create mode 100644 dist/bower_components/font-awesome/src/_includes/tell-me-thanks.html create mode 100644 dist/bower_components/font-awesome/src/_includes/tests/rotated-flipped-inside-anchor.html create mode 100644 dist/bower_components/font-awesome/src/_includes/tests/rotated-flipped-inside-btn.html create mode 100644 dist/bower_components/font-awesome/src/_includes/tests/rotated-flipped.html create mode 100644 dist/bower_components/font-awesome/src/_includes/tests/stacked-inside-anchor.html create mode 100644 dist/bower_components/font-awesome/src/_includes/tests/stacked.html create mode 100644 dist/bower_components/font-awesome/src/_includes/thanks-to.html create mode 100644 dist/bower_components/font-awesome/src/_includes/why.html create mode 100644 dist/bower_components/font-awesome/src/_layouts/base.html create mode 100644 dist/bower_components/font-awesome/src/_layouts/icon.html create mode 100644 dist/bower_components/font-awesome/src/_plugins/icon_page_generator.rb create mode 100644 dist/bower_components/font-awesome/src/_plugins/site.rb create mode 100644 dist/bower_components/font-awesome/src/assets/css/prettify.css create mode 100644 dist/bower_components/font-awesome/src/assets/css/pygments.css create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/fonts/FontAwesome.otf create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/fonts/fontawesome-webfont.eot create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/fonts/fontawesome-webfont.svg create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/fonts/fontawesome-webfont.ttf create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/fonts/fontawesome-webfont.woff create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/bordered-pulled.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/core.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/fixed-width.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/font-awesome.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/icons.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/larger.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/list.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/mixins.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/path.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/rotated-flipped.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/spinning.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/stacked.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/less/variables.less create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_bordered-pulled.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_core.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_fixed-width.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_icons.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_larger.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_list.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_mixins.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_path.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_rotated-flipped.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_spinning.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_stacked.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/_variables.scss create mode 100644 dist/bower_components/font-awesome/src/assets/font-awesome/scss/font-awesome.scss create mode 100644 dist/bower_components/font-awesome/src/assets/ico/favicon.ico create mode 100644 dist/bower_components/font-awesome/src/assets/js/ZeroClipboard-1.1.7.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/ZeroClipboard-1.1.7.swf create mode 100644 dist/bower_components/font-awesome/src/assets/js/backbone.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/bootstrap-2.3.1.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/bootstrap-222.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/bootstrap-3.0.0.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/html5shiv.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/jquery-1.10.2.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/jquery-1.10.2.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/jquery-1.10.2.min.map create mode 100644 dist/bower_components/font-awesome/src/assets/js/jquery-1.7.1.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/prettify.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/respond.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/site.js create mode 100644 dist/bower_components/font-awesome/src/assets/js/underscore.min.js create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/alerts.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/badges.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/bootstrap.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/breadcrumbs.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/button-groups.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/buttons.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/carousel.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/close.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/code.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/component-animations.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/dropdowns.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/forms.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/glyphicons.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/grid.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/input-groups.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/jumbotron.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/labels.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/list-group.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/media.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/mixins.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/modals.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/navbar.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/navs.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/normalize.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/pager.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/pagination.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/panels.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/popovers.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/print.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/progress-bars.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/responsive-utilities.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/scaffolding.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/tables.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/theme.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/thumbnails.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/tooltip.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/type.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/utilities.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/variables.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/bootstrap-3.0.0/wells.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/bootstrap/buttons.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/bootstrap/jumbotron.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/bootstrap/navbar.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/bootstrap/type.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/bootstrap/variables.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/bootstrap/wells.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/carbonad.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/example-rating.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/feature-list.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/fontawesome-icon-list.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/footer.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/jumbotron-carousel.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/layout.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/lazy.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/responsive/screen-lg.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/responsive/screen-md.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/responsive/screen-sm.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/responsive/screen-xs.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/social-buttons.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/stripe-ad.less create mode 100644 dist/bower_components/font-awesome/src/assets/less/site/textured-bg.less create mode 100644 dist/bower_components/font-awesome/src/cheatsheet.html create mode 100644 dist/bower_components/font-awesome/src/community.html create mode 100644 dist/bower_components/font-awesome/src/design.html create mode 100644 dist/bower_components/font-awesome/src/examples.html create mode 100644 dist/bower_components/font-awesome/src/get-started.html create mode 100644 dist/bower_components/font-awesome/src/glyphicons-test.html create mode 100644 dist/bower_components/font-awesome/src/icons.html create mode 100644 dist/bower_components/font-awesome/src/icons.yml create mode 100644 dist/bower_components/font-awesome/src/index.html create mode 100644 dist/bower_components/font-awesome/src/license.html create mode 100644 dist/bower_components/font-awesome/src/test-2.3.2.html create mode 100644 dist/bower_components/font-awesome/src/test.html create mode 100644 dist/bower_components/font-awesome/src/whats-new.html create mode 100644 dist/bower_components/jcrop/.bower.json create mode 100644 dist/bower_components/jcrop/MIT-LICENSE.txt create mode 100644 dist/bower_components/jcrop/README.md create mode 100644 dist/bower_components/jcrop/css/Jcrop.gif create mode 100644 dist/bower_components/jcrop/css/jquery.Jcrop.css create mode 100644 dist/bower_components/jcrop/css/jquery.Jcrop.min.css create mode 100644 dist/bower_components/jcrop/demos/crop.php create mode 100644 dist/bower_components/jcrop/demos/demo_files/demos.css create mode 100644 dist/bower_components/jcrop/demos/demo_files/main.css create mode 100644 dist/bower_components/jcrop/demos/demo_files/pool.jpg create mode 100644 dist/bower_components/jcrop/demos/demo_files/sago.jpg create mode 100644 dist/bower_components/jcrop/demos/demo_files/sagomod.jpg create mode 100644 dist/bower_components/jcrop/demos/demo_files/sagomod.png create mode 100644 dist/bower_components/jcrop/demos/non-image.html create mode 100644 dist/bower_components/jcrop/demos/styling.html create mode 100644 dist/bower_components/jcrop/demos/tutorial1.html create mode 100644 dist/bower_components/jcrop/demos/tutorial2.html create mode 100644 dist/bower_components/jcrop/demos/tutorial3.html create mode 100644 dist/bower_components/jcrop/demos/tutorial4.html create mode 100644 dist/bower_components/jcrop/demos/tutorial5.html create mode 100644 dist/bower_components/jcrop/index.html create mode 100644 dist/bower_components/jcrop/js/jquery.Jcrop.js create mode 100644 dist/bower_components/jcrop/js/jquery.Jcrop.min.js create mode 100644 dist/bower_components/jcrop/js/jquery.color.js create mode 100644 dist/bower_components/jcrop/js/jquery.min.js create mode 100644 dist/bower_components/jquery/.bower.json create mode 100644 dist/bower_components/jquery/MIT-LICENSE.txt create mode 100644 dist/bower_components/jquery/bower.json create mode 100644 dist/bower_components/jquery/dist/jquery.js create mode 100644 dist/bower_components/jquery/dist/jquery.min.js create mode 100644 dist/bower_components/jquery/dist/jquery.min.map create mode 100644 dist/bower_components/jquery/src/ajax.js create mode 100644 dist/bower_components/jquery/src/ajax/jsonp.js create mode 100644 dist/bower_components/jquery/src/ajax/load.js create mode 100644 dist/bower_components/jquery/src/ajax/parseJSON.js create mode 100644 dist/bower_components/jquery/src/ajax/parseXML.js create mode 100644 dist/bower_components/jquery/src/ajax/script.js create mode 100644 dist/bower_components/jquery/src/ajax/var/nonce.js create mode 100644 dist/bower_components/jquery/src/ajax/var/rquery.js create mode 100644 dist/bower_components/jquery/src/ajax/xhr.js create mode 100644 dist/bower_components/jquery/src/attributes.js create mode 100644 dist/bower_components/jquery/src/attributes/attr.js create mode 100644 dist/bower_components/jquery/src/attributes/classes.js create mode 100644 dist/bower_components/jquery/src/attributes/prop.js create mode 100644 dist/bower_components/jquery/src/attributes/support.js create mode 100644 dist/bower_components/jquery/src/attributes/val.js create mode 100644 dist/bower_components/jquery/src/callbacks.js create mode 100644 dist/bower_components/jquery/src/core.js create mode 100644 dist/bower_components/jquery/src/core/access.js create mode 100644 dist/bower_components/jquery/src/core/init.js create mode 100644 dist/bower_components/jquery/src/core/parseHTML.js create mode 100644 dist/bower_components/jquery/src/core/ready.js create mode 100644 dist/bower_components/jquery/src/core/var/rsingleTag.js create mode 100644 dist/bower_components/jquery/src/css.js create mode 100644 dist/bower_components/jquery/src/css/addGetHookIf.js create mode 100644 dist/bower_components/jquery/src/css/curCSS.js create mode 100644 dist/bower_components/jquery/src/css/defaultDisplay.js create mode 100644 dist/bower_components/jquery/src/css/hiddenVisibleSelectors.js create mode 100644 dist/bower_components/jquery/src/css/support.js create mode 100644 dist/bower_components/jquery/src/css/swap.js create mode 100644 dist/bower_components/jquery/src/css/var/cssExpand.js create mode 100644 dist/bower_components/jquery/src/css/var/getStyles.js create mode 100644 dist/bower_components/jquery/src/css/var/isHidden.js create mode 100644 dist/bower_components/jquery/src/css/var/rmargin.js create mode 100644 dist/bower_components/jquery/src/css/var/rnumnonpx.js create mode 100644 dist/bower_components/jquery/src/data.js create mode 100644 dist/bower_components/jquery/src/data/Data.js create mode 100644 dist/bower_components/jquery/src/data/accepts.js create mode 100644 dist/bower_components/jquery/src/data/var/data_priv.js create mode 100644 dist/bower_components/jquery/src/data/var/data_user.js create mode 100644 dist/bower_components/jquery/src/deferred.js create mode 100644 dist/bower_components/jquery/src/deprecated.js create mode 100644 dist/bower_components/jquery/src/dimensions.js create mode 100644 dist/bower_components/jquery/src/effects.js create mode 100644 dist/bower_components/jquery/src/effects/Tween.js create mode 100644 dist/bower_components/jquery/src/effects/animatedSelector.js create mode 100644 dist/bower_components/jquery/src/event.js create mode 100644 dist/bower_components/jquery/src/event/alias.js create mode 100644 dist/bower_components/jquery/src/event/support.js create mode 100644 dist/bower_components/jquery/src/exports/amd.js create mode 100644 dist/bower_components/jquery/src/exports/global.js create mode 100644 dist/bower_components/jquery/src/intro.js create mode 100644 dist/bower_components/jquery/src/jquery.js create mode 100644 dist/bower_components/jquery/src/manipulation.js create mode 100644 dist/bower_components/jquery/src/manipulation/_evalUrl.js create mode 100644 dist/bower_components/jquery/src/manipulation/support.js create mode 100644 dist/bower_components/jquery/src/manipulation/var/rcheckableType.js create mode 100644 dist/bower_components/jquery/src/offset.js create mode 100644 dist/bower_components/jquery/src/outro.js create mode 100644 dist/bower_components/jquery/src/queue.js create mode 100644 dist/bower_components/jquery/src/queue/delay.js create mode 100644 dist/bower_components/jquery/src/selector-native.js create mode 100644 dist/bower_components/jquery/src/selector-sizzle.js create mode 100644 dist/bower_components/jquery/src/selector.js create mode 100644 dist/bower_components/jquery/src/serialize.js create mode 100644 dist/bower_components/jquery/src/sizzle/dist/sizzle.js create mode 100644 dist/bower_components/jquery/src/sizzle/dist/sizzle.min.js create mode 100644 dist/bower_components/jquery/src/sizzle/dist/sizzle.min.map create mode 100644 dist/bower_components/jquery/src/traversing.js create mode 100644 dist/bower_components/jquery/src/traversing/findFilter.js create mode 100644 dist/bower_components/jquery/src/traversing/var/rneedsContext.js create mode 100644 dist/bower_components/jquery/src/var/arr.js create mode 100644 dist/bower_components/jquery/src/var/class2type.js create mode 100644 dist/bower_components/jquery/src/var/concat.js create mode 100644 dist/bower_components/jquery/src/var/hasOwn.js create mode 100644 dist/bower_components/jquery/src/var/indexOf.js create mode 100644 dist/bower_components/jquery/src/var/pnum.js create mode 100644 dist/bower_components/jquery/src/var/push.js create mode 100644 dist/bower_components/jquery/src/var/rnotwhite.js create mode 100644 dist/bower_components/jquery/src/var/slice.js create mode 100644 dist/bower_components/jquery/src/var/strundefined.js create mode 100644 dist/bower_components/jquery/src/var/support.js create mode 100644 dist/bower_components/jquery/src/var/toString.js create mode 100644 dist/bower_components/jquery/src/var/trim.js create mode 100644 dist/bower_components/jquery/src/wrap.js create mode 100644 dist/bower_components/json3/.bower.json create mode 100644 dist/bower_components/json3/LICENSE create mode 100644 dist/bower_components/json3/README.md create mode 100644 dist/bower_components/json3/bower.json create mode 100644 dist/bower_components/json3/lib/json3.js create mode 100644 dist/bower_components/json3/lib/json3.min.js create mode 100644 dist/bower_components/lodash/.bower.json create mode 100644 dist/bower_components/lodash/LICENSE.txt create mode 100644 dist/bower_components/lodash/bower.json create mode 100644 dist/bower_components/lodash/dist/lodash.compat.js create mode 100644 dist/bower_components/lodash/dist/lodash.compat.min.js create mode 100644 dist/bower_components/lodash/dist/lodash.js create mode 100644 dist/bower_components/lodash/dist/lodash.min.js create mode 100644 dist/bower_components/lodash/dist/lodash.underscore.js create mode 100644 dist/bower_components/lodash/dist/lodash.underscore.min.js create mode 100644 dist/bower_components/moment/.bower.json create mode 100644 dist/bower_components/moment/LICENSE create mode 100644 dist/bower_components/moment/bower.json create mode 100644 dist/bower_components/moment/lang/ar-ma.js create mode 100644 dist/bower_components/moment/lang/ar.js create mode 100644 dist/bower_components/moment/lang/bg.js create mode 100644 dist/bower_components/moment/lang/br.js create mode 100644 dist/bower_components/moment/lang/bs.js create mode 100644 dist/bower_components/moment/lang/ca.js create mode 100644 dist/bower_components/moment/lang/cs.js create mode 100644 dist/bower_components/moment/lang/cv.js create mode 100644 dist/bower_components/moment/lang/cy.js create mode 100644 dist/bower_components/moment/lang/da.js create mode 100644 dist/bower_components/moment/lang/de.js create mode 100644 dist/bower_components/moment/lang/el.js create mode 100644 dist/bower_components/moment/lang/en-au.js create mode 100644 dist/bower_components/moment/lang/en-ca.js create mode 100644 dist/bower_components/moment/lang/en-gb.js create mode 100644 dist/bower_components/moment/lang/eo.js create mode 100644 dist/bower_components/moment/lang/es.js create mode 100644 dist/bower_components/moment/lang/et.js create mode 100644 dist/bower_components/moment/lang/eu.js create mode 100644 dist/bower_components/moment/lang/fa.js create mode 100644 dist/bower_components/moment/lang/fi.js create mode 100644 dist/bower_components/moment/lang/fo.js create mode 100644 dist/bower_components/moment/lang/fr-ca.js create mode 100644 dist/bower_components/moment/lang/fr.js create mode 100644 dist/bower_components/moment/lang/gl.js create mode 100644 dist/bower_components/moment/lang/he.js create mode 100644 dist/bower_components/moment/lang/hi.js create mode 100644 dist/bower_components/moment/lang/hr.js create mode 100644 dist/bower_components/moment/lang/hu.js create mode 100644 dist/bower_components/moment/lang/hy-am.js create mode 100644 dist/bower_components/moment/lang/id.js create mode 100644 dist/bower_components/moment/lang/is.js create mode 100644 dist/bower_components/moment/lang/it.js create mode 100644 dist/bower_components/moment/lang/ja.js create mode 100644 dist/bower_components/moment/lang/ka.js create mode 100644 dist/bower_components/moment/lang/ko.js create mode 100644 dist/bower_components/moment/lang/lb.js create mode 100644 dist/bower_components/moment/lang/lt.js create mode 100644 dist/bower_components/moment/lang/lv.js create mode 100644 dist/bower_components/moment/lang/mk.js create mode 100644 dist/bower_components/moment/lang/ml.js create mode 100644 dist/bower_components/moment/lang/mr.js create mode 100644 dist/bower_components/moment/lang/ms-my.js create mode 100644 dist/bower_components/moment/lang/nb.js create mode 100644 dist/bower_components/moment/lang/ne.js create mode 100644 dist/bower_components/moment/lang/nl.js create mode 100644 dist/bower_components/moment/lang/nn.js create mode 100644 dist/bower_components/moment/lang/pl.js create mode 100644 dist/bower_components/moment/lang/pt-br.js create mode 100644 dist/bower_components/moment/lang/pt.js create mode 100644 dist/bower_components/moment/lang/ro.js create mode 100644 dist/bower_components/moment/lang/rs.js create mode 100644 dist/bower_components/moment/lang/ru.js create mode 100644 dist/bower_components/moment/lang/sk.js create mode 100644 dist/bower_components/moment/lang/sl.js create mode 100644 dist/bower_components/moment/lang/sq.js create mode 100644 dist/bower_components/moment/lang/sv.js create mode 100644 dist/bower_components/moment/lang/ta.js create mode 100644 dist/bower_components/moment/lang/th.js create mode 100644 dist/bower_components/moment/lang/tl-ph.js create mode 100644 dist/bower_components/moment/lang/tr.js create mode 100644 dist/bower_components/moment/lang/tzm-la.js create mode 100644 dist/bower_components/moment/lang/tzm.js create mode 100644 dist/bower_components/moment/lang/uk.js create mode 100644 dist/bower_components/moment/lang/uz.js create mode 100644 dist/bower_components/moment/lang/vn.js create mode 100644 dist/bower_components/moment/lang/zh-cn.js create mode 100644 dist/bower_components/moment/lang/zh-tw.js create mode 100644 dist/bower_components/moment/min/langs.js create mode 100644 dist/bower_components/moment/min/langs.min.js create mode 100644 dist/bower_components/moment/min/moment-with-langs.js create mode 100644 dist/bower_components/moment/min/moment-with-langs.min.js create mode 100644 dist/bower_components/moment/min/moment.min.js create mode 100644 dist/bower_components/moment/moment.js create mode 100644 dist/bower_components/moment/readme.md create mode 100644 dist/bower_components/nprogress/.bower.json create mode 100644 dist/bower_components/nprogress/History.md create mode 100644 dist/bower_components/nprogress/License.md create mode 100644 dist/bower_components/nprogress/Notes.md create mode 100644 dist/bower_components/nprogress/Readme.md create mode 100644 dist/bower_components/nprogress/bower.json create mode 100644 dist/bower_components/nprogress/component.json create mode 100644 dist/bower_components/nprogress/index.html create mode 100644 dist/bower_components/nprogress/nprogress.css create mode 100644 dist/bower_components/nprogress/nprogress.js create mode 100644 dist/bower_components/nprogress/package.json create mode 100644 dist/bower_components/nprogress/support/extras.css create mode 100644 dist/bower_components/nprogress/support/style.css create mode 100644 dist/bower_components/nprogress/test/component.html create mode 100644 dist/bower_components/nprogress/test/index.html create mode 100644 dist/bower_components/nprogress/test/setup.js create mode 100644 dist/bower_components/nprogress/test/support/multisuite.js create mode 100644 dist/bower_components/nprogress/test/test.js create mode 100644 dist/bower_components/nprogress/vendor/chai.js create mode 100644 dist/bower_components/nprogress/vendor/jquery-1.10.js create mode 100644 dist/bower_components/nprogress/vendor/jquery-1.7.js create mode 100644 dist/bower_components/nprogress/vendor/jquery-1.8.js create mode 100644 dist/bower_components/nprogress/vendor/jquery-1.9.js create mode 100644 dist/bower_components/nprogress/vendor/jquery-2.0.js create mode 100644 dist/bower_components/nprogress/vendor/mocha.css create mode 100644 dist/bower_components/nprogress/vendor/mocha.js create mode 100644 dist/bower_components/onion-editor/.bower.json create mode 100644 dist/bower_components/onion-editor/Gruntfile.js create mode 100644 dist/bower_components/onion-editor/LICENSE create mode 100644 dist/bower_components/onion-editor/README.md create mode 100644 dist/bower_components/onion-editor/bower.json create mode 100644 dist/bower_components/onion-editor/build/onion-editor.js create mode 100644 dist/bower_components/onion-editor/build/onion-editor.min.js create mode 100644 dist/bower_components/onion-editor/package.json create mode 100644 dist/bower_components/raven-js/.bower.json create mode 100644 dist/bower_components/raven-js/.gitignore create mode 100644 dist/bower_components/raven-js/.jshintrc create mode 100644 dist/bower_components/raven-js/.travis.yml create mode 100644 dist/bower_components/raven-js/AUTHORS create mode 100644 dist/bower_components/raven-js/Gruntfile.js create mode 100644 dist/bower_components/raven-js/LICENSE create mode 100644 dist/bower_components/raven-js/Makefile create mode 100644 dist/bower_components/raven-js/README.md create mode 100644 dist/bower_components/raven-js/bower.json create mode 100644 dist/bower_components/raven-js/dist/raven.js create mode 100644 dist/bower_components/raven-js/dist/raven.min.js create mode 100644 dist/bower_components/raven-js/dist/raven.min.map create mode 100644 dist/bower_components/raven-js/docs/Makefile create mode 100644 dist/bower_components/raven-js/docs/changelog/index.rst create mode 100644 dist/bower_components/raven-js/docs/conf.py create mode 100644 dist/bower_components/raven-js/docs/config/index.rst create mode 100644 dist/bower_components/raven-js/docs/contributing/index.rst create mode 100644 dist/bower_components/raven-js/docs/index.rst create mode 100644 dist/bower_components/raven-js/docs/install/index.rst create mode 100644 dist/bower_components/raven-js/docs/make.bat create mode 100644 dist/bower_components/raven-js/docs/plugins/index.rst create mode 100644 dist/bower_components/raven-js/docs/tips/index.rst create mode 100644 dist/bower_components/raven-js/docs/usage/index.rst create mode 100644 dist/bower_components/raven-js/example/Makefile create mode 100644 dist/bower_components/raven-js/example/file.min.js create mode 100644 dist/bower_components/raven-js/example/file.sourcemap.js create mode 100644 dist/bower_components/raven-js/example/file1.js create mode 100644 dist/bower_components/raven-js/example/file2.js create mode 100644 dist/bower_components/raven-js/example/index.html create mode 100644 dist/bower_components/raven-js/example/scratch.js create mode 100644 dist/bower_components/raven-js/package.json create mode 100644 dist/bower_components/raven-js/plugins/console.js create mode 100644 dist/bower_components/raven-js/plugins/jquery.js create mode 100644 dist/bower_components/raven-js/plugins/native.js create mode 100644 dist/bower_components/raven-js/plugins/require.js create mode 100644 dist/bower_components/raven-js/src/raven.js create mode 100644 dist/bower_components/raven-js/template/_copyright.js create mode 100644 dist/bower_components/raven-js/template/_footer.js create mode 100644 dist/bower_components/raven-js/template/_header.js create mode 100644 dist/bower_components/raven-js/test/index.html create mode 100644 dist/bower_components/raven-js/test/raven.test.js create mode 100644 dist/bower_components/raven-js/vendor/TraceKit/tracekit.js create mode 100644 dist/bower_components/restangular/.bower.json create mode 100644 dist/bower_components/restangular/.gitignore create mode 100644 dist/bower_components/restangular/.travis.yml create mode 100644 dist/bower_components/restangular/CHANGELOG.md create mode 100644 dist/bower_components/restangular/CONTRIBUTE.md create mode 100644 dist/bower_components/restangular/Gruntfile.js create mode 100644 dist/bower_components/restangular/README.md create mode 100644 dist/bower_components/restangular/bower.json create mode 100644 dist/bower_components/restangular/dist/restangular.js create mode 100644 dist/bower_components/restangular/dist/restangular.min.js create mode 100644 dist/bower_components/restangular/dist/restangular.zip create mode 100644 dist/bower_components/restangular/karma.conf.js create mode 100644 dist/bower_components/restangular/karma.underscore.conf.js create mode 100644 dist/bower_components/restangular/license.md create mode 100644 dist/bower_components/restangular/package.json create mode 100644 dist/bower_components/restangular/src/restangular.js create mode 100644 dist/bower_components/restangular/test/restangularSpec.js create mode 100644 dist/bower_components/underscore/.bower.json create mode 100644 dist/bower_components/underscore/.editorconfig create mode 100644 dist/bower_components/underscore/.gitignore create mode 100644 dist/bower_components/underscore/LICENSE create mode 100644 dist/bower_components/underscore/README.md create mode 100644 dist/bower_components/underscore/bower.json create mode 100644 dist/bower_components/underscore/component.json create mode 100644 dist/bower_components/underscore/package.json create mode 100644 dist/bower_components/underscore/underscore.js create mode 100644 dist/bower_components/urlify/.bower.json create mode 100644 dist/bower_components/urlify/LICENSE create mode 100644 dist/bower_components/urlify/README.md create mode 100644 dist/bower_components/urlify/urlify.js create mode 100644 dist/favicon.ico create mode 100644 dist/fonts/fontawesome-webfont.eot create mode 100644 dist/fonts/fontawesome-webfont.svg create mode 100644 dist/fonts/fontawesome-webfont.ttf create mode 100644 dist/fonts/fontawesome-webfont.woff create mode 100644 dist/fonts/glyphicons-halflings-regular.eot create mode 100644 dist/fonts/glyphicons-halflings-regular.svg create mode 100644 dist/fonts/glyphicons-halflings-regular.ttf create mode 100644 dist/fonts/glyphicons-halflings-regular.woff create mode 100644 dist/images/loading.gif create mode 100644 dist/images/onion.png create mode 100644 dist/index.html create mode 100644 dist/robots.txt create mode 100644 dist/scripts/scripts.js create mode 100644 dist/scripts/templates.js create mode 100644 dist/scripts/vendor.js create mode 100644 dist/styles/Jcrop.gif create mode 100644 dist/styles/font-awesome.min.css create mode 100644 dist/styles/vendor.css diff --git a/.gitignore b/.gitignore index 4f6bf23c3..886993524 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ node_modules -dist .tmp .sass-cache app/bower_components diff --git a/dist/.htaccess b/dist/.htaccess new file mode 100644 index 000000000..cb84cb918 --- /dev/null +++ b/dist/.htaccess @@ -0,0 +1,543 @@ +# Apache Configuration File + +# (!) Using `.htaccess` files slows down Apache, therefore, if you have access +# to the main server config file (usually called `httpd.conf`), you should add +# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html. + +# ############################################################################## +# # CROSS-ORIGIN RESOURCE SHARING (CORS) # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Cross-domain AJAX requests | +# ------------------------------------------------------------------------------ + +# Enable cross-origin AJAX requests. +# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity +# http://enable-cors.org/ + +# +# Header set Access-Control-Allow-Origin "*" +# + +# ------------------------------------------------------------------------------ +# | CORS-enabled images | +# ------------------------------------------------------------------------------ + +# Send the CORS header for images when browsers request it. +# https://developer.mozilla.org/en/CORS_Enabled_Image +# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html +# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ + + + + + SetEnvIf Origin ":" IS_CORS + Header set Access-Control-Allow-Origin "*" env=IS_CORS + + + + +# ------------------------------------------------------------------------------ +# | Web fonts access | +# ------------------------------------------------------------------------------ + +# Allow access from all domains for web fonts + + + + Header set Access-Control-Allow-Origin "*" + + + + +# ############################################################################## +# # ERRORS # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | 404 error prevention for non-existing redirected folders | +# ------------------------------------------------------------------------------ + +# Prevent Apache from returning a 404 error for a rewrite if a directory +# with the same name does not exist. +# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews +# http://www.webmasterworld.com/apache/3808792.htm + +Options -MultiViews + +# ------------------------------------------------------------------------------ +# | Custom error messages / pages | +# ------------------------------------------------------------------------------ + +# You can customize what Apache returns to the client in case of an error (see +# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.: + +ErrorDocument 404 /404.html + + +# ############################################################################## +# # INTERNET EXPLORER # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Better website experience | +# ------------------------------------------------------------------------------ + +# Force IE to render pages in the highest available mode in the various +# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf. + + + Header set X-UA-Compatible "IE=edge" + # `mod_headers` can't match based on the content-type, however, we only + # want to send this header for HTML pages and not for the other resources + + Header unset X-UA-Compatible + + + +# ------------------------------------------------------------------------------ +# | Cookie setting from iframes | +# ------------------------------------------------------------------------------ + +# Allow cookies to be set from iframes in IE. + +# +# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" +# + +# ------------------------------------------------------------------------------ +# | Screen flicker | +# ------------------------------------------------------------------------------ + +# Stop screen flicker in IE on CSS rollovers (this only works in +# combination with the `ExpiresByType` directives for images from below). + +# BrowserMatch "MSIE" brokenvary=1 +# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 +# BrowserMatch "Opera" !brokenvary +# SetEnvIf brokenvary 1 force-no-vary + + +# ############################################################################## +# # MIME TYPES AND ENCODING # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Proper MIME types for all files | +# ------------------------------------------------------------------------------ + + + + # Audio + AddType audio/mp4 m4a f4a f4b + AddType audio/ogg oga ogg + + # JavaScript + # Normalize to standard type (it's sniffed in IE anyways): + # http://tools.ietf.org/html/rfc4329#section-7.2 + AddType application/javascript js jsonp + AddType application/json json + + # Video + AddType video/mp4 mp4 m4v f4v f4p + AddType video/ogg ogv + AddType video/webm webm + AddType video/x-flv flv + + # Web fonts + AddType application/font-woff woff + AddType application/vnd.ms-fontobject eot + + # Browsers usually ignore the font MIME types and sniff the content, + # however, Chrome shows a warning if other MIME types are used for the + # following fonts. + AddType application/x-font-ttf ttc ttf + AddType font/opentype otf + + # Make SVGZ fonts work on iPad: + # https://twitter.com/FontSquirrel/status/14855840545 + AddType image/svg+xml svg svgz + AddEncoding gzip svgz + + # Other + AddType application/octet-stream safariextz + AddType application/x-chrome-extension crx + AddType application/x-opera-extension oex + AddType application/x-shockwave-flash swf + AddType application/x-web-app-manifest+json webapp + AddType application/x-xpinstall xpi + AddType application/xml atom rdf rss xml + AddType image/webp webp + AddType image/x-icon ico + AddType text/cache-manifest appcache manifest + AddType text/vtt vtt + AddType text/x-component htc + AddType text/x-vcard vcf + + + +# ------------------------------------------------------------------------------ +# | UTF-8 encoding | +# ------------------------------------------------------------------------------ + +# Use UTF-8 encoding for anything served as `text/html` or `text/plain`. +AddDefaultCharset utf-8 + +# Force UTF-8 for certain file formats. + + AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml + + + +# ############################################################################## +# # URL REWRITES # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Rewrite engine | +# ------------------------------------------------------------------------------ + +# Turning on the rewrite engine and enabling the `FollowSymLinks` option is +# necessary for the following directives to work. + +# If your web host doesn't allow the `FollowSymlinks` option, you may need to +# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the +# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks + +# Also, some cloud hosting services require `RewriteBase` to be set: +# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site + + + Options +FollowSymlinks + # Options +SymLinksIfOwnerMatch + RewriteEngine On + # RewriteBase / + + +# ------------------------------------------------------------------------------ +# | Suppressing / Forcing the "www." at the beginning of URLs | +# ------------------------------------------------------------------------------ + +# The same content should never be available under two different URLs especially +# not with and without "www." at the beginning. This can cause SEO problems +# (duplicate content), therefore, you should choose one of the alternatives and +# redirect the other one. + +# By default option 1 (no "www.") is activated: +# http://no-www.org/faq.php?q=class_b + +# If you'd prefer to use option 2, just comment out all the lines from option 1 +# and uncomment the ones from option 2. + +# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Option 1: rewrite www.example.com → example.com + + + RewriteCond %{HTTPS} !=on + RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] + RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Option 2: rewrite example.com → www.example.com + +# Be aware that the following might not be a good idea if you use "real" +# subdomains for certain parts of your website. + +# +# RewriteCond %{HTTPS} !=on +# RewriteCond %{HTTP_HOST} !^www\..+$ [NC] +# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] +# + + +# ############################################################################## +# # SECURITY # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Content Security Policy (CSP) | +# ------------------------------------------------------------------------------ + +# You can mitigate the risk of cross-site scripting and other content-injection +# attacks by setting a Content Security Policy which whitelists trusted sources +# of content for your site. + +# The example header below allows ONLY scripts that are loaded from the current +# site's origin (no inline scripts, no CDN, etc). This almost certainly won't +# work as-is for your site! + +# To get all the details you'll need to craft a reasonable policy for your site, +# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or +# see the specification: http://w3.org/TR/CSP). + +# +# Header set Content-Security-Policy "script-src 'self'; object-src 'self'" +# +# Header unset Content-Security-Policy +# +# + +# ------------------------------------------------------------------------------ +# | File access | +# ------------------------------------------------------------------------------ + +# Block access to directories without a default document. +# Usually you should leave this uncommented because you shouldn't allow anyone +# to surf through every directory on your server (which may includes rather +# private places like the CMS's directories). + + + Options -Indexes + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Block access to hidden files and directories. +# This includes directories used by version control systems such as Git and SVN. + + + RewriteCond %{SCRIPT_FILENAME} -d [OR] + RewriteCond %{SCRIPT_FILENAME} -f + RewriteRule "(^|/)\." - [F] + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Block access to backup and source files. +# These files may be left by some text editors and can pose a great security +# danger when anyone has access to them. + + + Order allow,deny + Deny from all + Satisfy All + + +# ------------------------------------------------------------------------------ +# | Secure Sockets Layer (SSL) | +# ------------------------------------------------------------------------------ + +# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.: +# prevent `https://www.example.com` when your certificate only allows +# `https://secure.example.com`. + +# +# RewriteCond %{SERVER_PORT} !^443 +# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] +# + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Force client-side SSL redirection. + +# If a user types "example.com" in his browser, the above rule will redirect him +# to the secure version of the site. That still leaves a window of opportunity +# (the initial HTTP connection) for an attacker to downgrade or redirect the +# request. The following header ensures that browser will ONLY connect to your +# server via HTTPS, regardless of what the users type in the address bar. +# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/ + +# +# Header set Strict-Transport-Security max-age=16070400; +# + +# ------------------------------------------------------------------------------ +# | Server software information | +# ------------------------------------------------------------------------------ + +# Avoid displaying the exact Apache version number, the description of the +# generic OS-type and the information about Apache's compiled-in modules. + +# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`! + +# ServerTokens Prod + + +# ############################################################################## +# # WEB PERFORMANCE # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Compression | +# ------------------------------------------------------------------------------ + + + + # Force compression for mangled headers. + # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping + + + SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding + RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding + + + + # Compress all output labeled with one of the following MIME-types + # (for Apache versions below 2.3.7, you don't need to enable `mod_filter` + # and can remove the `` and `` lines + # as `AddOutputFilterByType` is still in the core directives). + + AddOutputFilterByType DEFLATE application/atom+xml \ + application/javascript \ + application/json \ + application/rss+xml \ + application/vnd.ms-fontobject \ + application/x-font-ttf \ + application/x-web-app-manifest+json \ + application/xhtml+xml \ + application/xml \ + font/opentype \ + image/svg+xml \ + image/x-icon \ + text/css \ + text/html \ + text/plain \ + text/x-component \ + text/xml + + + + +# ------------------------------------------------------------------------------ +# | Content transformations | +# ------------------------------------------------------------------------------ + +# Prevent some of the mobile network providers from modifying the content of +# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5. + +# +# Header set Cache-Control "no-transform" +# + +# ------------------------------------------------------------------------------ +# | ETag removal | +# ------------------------------------------------------------------------------ + +# Since we're sending far-future expires headers (see below), ETags can +# be removed: http://developer.yahoo.com/performance/rules.html#etags. + +# `FileETag None` is not enough for every server. + + Header unset ETag + + +FileETag None + +# ------------------------------------------------------------------------------ +# | Expires headers (for better cache control) | +# ------------------------------------------------------------------------------ + +# The following expires headers are set pretty far in the future. If you don't +# control versioning with filename-based cache busting, consider lowering the +# cache time for resources like CSS and JS to something like 1 week. + + + + ExpiresActive on + ExpiresDefault "access plus 1 month" + + # CSS + ExpiresByType text/css "access plus 1 year" + + # Data interchange + ExpiresByType application/json "access plus 0 seconds" + ExpiresByType application/xml "access plus 0 seconds" + ExpiresByType text/xml "access plus 0 seconds" + + # Favicon (cannot be renamed!) + ExpiresByType image/x-icon "access plus 1 week" + + # HTML components (HTCs) + ExpiresByType text/x-component "access plus 1 month" + + # HTML + ExpiresByType text/html "access plus 0 seconds" + + # JavaScript + ExpiresByType application/javascript "access plus 1 year" + + # Manifest files + ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" + ExpiresByType text/cache-manifest "access plus 0 seconds" + + # Media + ExpiresByType audio/ogg "access plus 1 month" + ExpiresByType image/gif "access plus 1 month" + ExpiresByType image/jpeg "access plus 1 month" + ExpiresByType image/png "access plus 1 month" + ExpiresByType video/mp4 "access plus 1 month" + ExpiresByType video/ogg "access plus 1 month" + ExpiresByType video/webm "access plus 1 month" + + # Web feeds + ExpiresByType application/atom+xml "access plus 1 hour" + ExpiresByType application/rss+xml "access plus 1 hour" + + # Web fonts + ExpiresByType application/font-woff "access plus 1 month" + ExpiresByType application/vnd.ms-fontobject "access plus 1 month" + ExpiresByType application/x-font-ttf "access plus 1 month" + ExpiresByType font/opentype "access plus 1 month" + ExpiresByType image/svg+xml "access plus 1 month" + + + +# ------------------------------------------------------------------------------ +# | Filename-based cache busting | +# ------------------------------------------------------------------------------ + +# If you're not using a build process to manage your filename version revving, +# you might want to consider enabling the following directives to route all +# requests such as `/css/style.12345.css` to `/css/style.css`. + +# To understand why this is important and a better idea than `*.css?v231`, read: +# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring + +# +# RewriteCond %{REQUEST_FILENAME} !-f +# RewriteCond %{REQUEST_FILENAME} !-d +# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] +# + +# ------------------------------------------------------------------------------ +# | File concatenation | +# ------------------------------------------------------------------------------ + +# Allow concatenation from within specific CSS and JS files, e.g.: +# Inside of `script.combined.js` you could have +# +# +# and they would be included into this single file. + +# +# +# Options +Includes +# AddOutputFilterByType INCLUDES application/javascript application/json +# SetOutputFilter INCLUDES +# +# +# Options +Includes +# AddOutputFilterByType INCLUDES text/css +# SetOutputFilter INCLUDES +# +# + +# ------------------------------------------------------------------------------ +# | Persistent connections | +# ------------------------------------------------------------------------------ + +# Allow multiple requests to be sent over the same TCP connection: +# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive. + +# Enable if you serve a lot of static content but, be aware of the +# possible disadvantages! + +# +# Header set Connection Keep-Alive +# diff --git a/dist/404.html b/dist/404.html new file mode 100644 index 000000000..ec98e3c26 --- /dev/null +++ b/dist/404.html @@ -0,0 +1,157 @@ + + + + + Page Not Found :( + + + +
+

Not found :(

+

Sorry, but the page you were trying to view does not exist.

+

It looks like this was the result of either:

+
    +
  • a mistyped address
  • +
  • an out-of-date link
  • +
+ + +
+ + diff --git a/dist/bower_components/angular-bootstrap-datetimepicker/.bower.json b/dist/bower_components/angular-bootstrap-datetimepicker/.bower.json new file mode 100644 index 000000000..ea12d03a2 --- /dev/null +++ b/dist/bower_components/angular-bootstrap-datetimepicker/.bower.json @@ -0,0 +1,43 @@ +{ + "name": "angular-bootstrap-datetimepicker", + "version": "0.2.2", + "description": "This directive allows you to add a datetime-picker to your form.", + "author": "https://github.com/dalelotts/angular-bootstrap-datetimepicker/graphs/contributors", + "license": "MIT", + "homepage": "http://dalelotts.github.io/angular-bootstrap-datetimepicker", + "main": [ + "./src/js/datetimepicker.js", + "./src/css/datetimepicker.css" + ], + "ignore": [ + "**/.*", + "screenshots", + "node_modules", + "bower_components", + "test*", + "demo*", + "Gruntfile.js", + "package.json" + ], + "dependencies": { + "angular": "1.2.11", + "bootstrap": "3.1.0", + "moment": "2.5.1" + }, + "devDependencies": { + "angular-mocks": "1.2.11", + "jquery": "2.1.0" + }, + "resolutions": { + "angular": "1.2.11" + }, + "_release": "0.2.2", + "_resolution": { + "type": "version", + "tag": "0.2.2", + "commit": "6472006131bcc1b0342bb9bfc43e0225ae972329" + }, + "_source": "git://github.com/dalelotts/angular-bootstrap-datetimepicker.git", + "_target": "~0.2.2", + "_originalSource": "angular-bootstrap-datetimepicker" +} \ No newline at end of file diff --git a/dist/bower_components/angular-bootstrap-datetimepicker/LICENSE b/dist/bower_components/angular-bootstrap-datetimepicker/LICENSE new file mode 100644 index 000000000..baacf3914 --- /dev/null +++ b/dist/bower_components/angular-bootstrap-datetimepicker/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2013 Dale Lotts + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/dist/bower_components/angular-bootstrap-datetimepicker/README.md b/dist/bower_components/angular-bootstrap-datetimepicker/README.md new file mode 100644 index 000000000..0f8c9157d --- /dev/null +++ b/dist/bower_components/angular-bootstrap-datetimepicker/README.md @@ -0,0 +1,244 @@ +# Angular bootstrap date & time picker v0.2.2 +================================ + +Native AngularJS datetime picker directive styled by Twitter Bootstrap 3 +[![Build Status](https://travis-ci.org/dalelotts/angular-bootstrap-datetimepicker.png?branch=master)](https://travis-ci.org/dalelotts/angular-bootstrap-datetimepicker) +[![devDependency Status](https://david-dm.org/dalelotts/angular-bootstrap-datetimepicker/dev-status.png)](https://david-dm.org/dalelotts/angular-bootstrap-datetimepicker#info=devDependencies) +[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/dalelotts/angular-bootstrap-datetimepicker/trend.png)](https://bitdeli.com/free "Bitdeli Badge") + +[Home / demo page](http://dalelotts.github.io/angular-bootstrap-datetimepicker/) + +# (Almost) Complete re-write + +This project started as an AngularJS specific re-write of the [bootstrap-datetimepicker project](https://github.com/smalot/bootstrap-datetimepicker). +Only the CSS file from the bootstrap-datetimepicker project was re-used. + +#Dependencies + +Requires: + * AngularJS 1.2.11 or higher (1.0.x will not work) + * moment.js for date parsing and formatting + * bootstrap's dropdown component (`dropdowns.less`) + * bootstrap's glyphicons for arrows + +#Testing +We use karma and jshint to ensure the quality of the code. The easiest way to run these checks is to use grunt: + +``` +npm install -g grunt-cli +npm install +``` + +The karma task will try to open Chrome as a browser in which to run the tests. Make sure this is available or change the configuration in test\test.config.js + +#Usage +We use bower for dependency management. Add + +```json +dependencies: { + "angular-bootstrap-datetimepicker": "latest" +} +``` + +To your bower.json file. Then run + +```html +bower install +``` + +This will copy the angular-bootstrap-datetimepicker files into your components folder, along with its dependencies. + +Add the css: + +```html + + +``` + +Load the script files in your application: +```html + + + + +``` + +Add the date module as a dependency to your application module: + +```html +var myAppModule = angular.module('MyApp', ['ui.bootstrap.datetimepicker']) +``` + +Apply the directive to your form elements: + +```html + +``` + +## Options + +### on-set-time +Attribute on datetimepicker + +If the value of the on-set-time attribute is a function, the date time picker will call this function +passing in the selected value and previous value. +```html + +``` +This function will be called when the user selects a value on the minView. +```javascript +$scope.onTimeSet = function (newDate, oldDate) { + console.log(newDate); + console.log(oldDate); +} +``` + +### startView + +String. Default: 'day' + +The view that the datetimepicker should show when it is opened. +Accepts values of : + * 'minute' for the minute view + * 'hour' for the hour view + * 'day' for the day view (the default) + * 'month' for the 12-month view + * 'year' for the 10-year overview. Useful for date-of-birth datetimepickers. + +### minView + +String. 'minute' + +The lowest view that the datetimepicker should show. + +### minuteStep + +Number. Default: 5 + +The increment used to build the hour view. A button is created for each minuteStep minutes. + +### dropdownSelector + +When used within a Bootstrap dropdown, the selector specified in dropdownSelector will toggle the dropdown when a date/time is selected. + +### weekStart + +Number. Default: 0 + +Allows to set a week's starting day. Should be between 0 and 6. + +```html + +``` + + +## Working with ng-model +The angular-bootstrap-datetimepicker directive requires ng-model and the picked date/time is automatically synchronized with the model value. + +This directive also plays nicely with validation directives such as ng-required. + +The angular-bootstrap-datetimepicker directive stores and expects the model value to be a standard javascript Date object. + +## ng-required directive +If you apply the required directive to element then the form element is invalid until a date is picked. + +Note: Remember that the ng-required directive must be explicitly set, i.e. to "true". + +## Examples + +### Inline component. + +```html + +``` +### Inline component with data bound to the page with the format specified via date filter: + +```html + +``` +``` +

Selected Date: {{ data.date | date:'yyyy-MM-dd HH:mm' }}

+``` + +Display formatting of the date field is controlled by Angular filters. + +### As a drop-down: + +```html + +``` +In this example, the drop-down functionality is controlled by Twitter Bootstrap. +The dropdownSelector tells the datetimepicker which element is bound to the Twitter Bootstrap drop-down so +the drop-down is toggled closed after the user selectes a date/time. + +### Drop-down component with associated input box. +```html + +``` +In this example, the drop-down functionality is controlled by Twitter Bootstrap. +The dropdownSelector tells the datetimepicker which element is bound to the Twitter Bootstrap drop-down so +the drop-down is toggled closed after the user selectes a date/time. + +## I18N + +All internationalization is handled by Moment.js, see Moment's documention for details. + +# Screenshots + +## Year view + +![Datetimepicker year view](https://raw.github.com/dalelotts/angular-bootstrap-datetimepicker/master/screenshots/year.png) + +This view allows the user to select the year for the target date. +If the year view is the minView, the date will be set to midnight on the first day of the year + +## Month view + +![Datetimepicker month view](https://raw.github.com/dalelotts/angular-bootstrap-datetimepicker/master/screenshots/month.png) + +This view allows the user to select the month in the selected year. +If the month view is the minView, the date will be set to midnight on the first day of the month. + +## Day view (Default) + +![Datetimepicker day view](https://raw.github.com/dalelotts/angular-bootstrap-datetimepicker/master/screenshots/day.png) + +This view allows the user to select the the day of the month, in the selected month. +If the day view is the minView, the date will be set to midnight on the day selected. + +## Hour view + +![Datetimepicker hour view](https://raw.github.com/dalelotts/angular-bootstrap-datetimepicker/master/screenshots/hour.png) + +This view allows the user to select the hour of the day, on the selected day. +If the hour view is the minView, the date will be set to the beginning of the hour on the day selected. + +## Minute view + +![Datetimepicker minute view](https://raw.github.com/dalelotts/angular-bootstrap-datetimepicker/master/screenshots/minute.png) + +This view allows the user to select a specific time of day, in the selected hour. +By default, the time is displayed in 5 minute increments. The minuteStep property controls the increments of time displayed. +If the minute view is the minView, which is is by default, the date will be set to the beginning of the hour on the day selected. + +# Idea Project Directory + +The .idea directory holds the IntelliJ Idea project files for this project. If you use Idea, just open the project with Idea. diff --git a/dist/bower_components/angular-bootstrap-datetimepicker/bower.json b/dist/bower_components/angular-bootstrap-datetimepicker/bower.json new file mode 100644 index 000000000..42d39f705 --- /dev/null +++ b/dist/bower_components/angular-bootstrap-datetimepicker/bower.json @@ -0,0 +1,34 @@ +{ + "name": "angular-bootstrap-datetimepicker", + "version": "0.2.2", + "description": "This directive allows you to add a datetime-picker to your form.", + "author": "https://github.com/dalelotts/angular-bootstrap-datetimepicker/graphs/contributors", + "license": "MIT", + "homepage": "http://dalelotts.github.io/angular-bootstrap-datetimepicker", + "main": [ + "./src/js/datetimepicker.js", + "./src/css/datetimepicker.css" + ], + "ignore": [ + "**/.*", + "screenshots", + "node_modules", + "bower_components", + "test*", + "demo*", + "Gruntfile.js", + "package.json" + ], + "dependencies": { + "angular": "1.2.11", + "bootstrap": "3.1.0", + "moment": "2.5.1" + }, + "devDependencies": { + "angular-mocks": "1.2.11", + "jquery": "2.1.0" + }, + "resolutions": { + "angular": "1.2.11" + } +} diff --git a/dist/bower_components/angular-bootstrap-datetimepicker/karma.conf.js b/dist/bower_components/angular-bootstrap-datetimepicker/karma.conf.js new file mode 100644 index 000000000..d7256177d --- /dev/null +++ b/dist/bower_components/angular-bootstrap-datetimepicker/karma.conf.js @@ -0,0 +1,91 @@ +/*globals module */ + +/** + * @license angular-bootstrap-datetimepicker + * (c) 2013 Knight Rider Consulting, Inc. http://www.knightrider.com + * License: MIT + */ + +/** + * + * @author Dale "Ducky" Lotts + * @since 7/21/13 + */ + +module.exports = function (config) { + 'use strict'; + config.set({ + + frameworks: ['jasmine'], + + plugins: [ + 'karma-jasmine', + 'karma-chrome-launcher', + 'karma-firefox-launcher', + 'karma-coverage' + ], + + files: [ + 'bower_components/jquery/jquery.js', + 'bower_components/moment/moment.js', + 'bower_components/bootstrap/dist/js/bootstrap.js', + 'bower_components/angular/angular.js', + 'bower_components/angular-mocks/angular-mocks.js', + 'src/js/datetimepicker.js', + 'test/*.spec.js' + ], + + // list of files to exclude + exclude: [ + + ], + + preprocessors: { + '**/src/js/*.js': ['coverage'] + }, + + // test results reporter to use + // possible values: 'dots', 'progress', 'junit' + reporters: ['progress', 'coverage'], + + // web server port + port: 9876, + + + // cli runner port + runnerPort: 9100, + + + // enable / disable colors in the output (reporters and logs) + colors: true, + + + // level of logging + // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG + logLevel: config.LOG_INFO, + + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + + + // Start these browsers, currently available: + // - Chrome + // - ChromeCanary + // - Firefox + // - Opera + // - Safari (only Mac) + // - PhantomJS + // - IE (only Windows) + browsers: ['Chrome'], + + + // If browser does not capture in given timeout [ms], kill it + captureTimeout: 60000, + + + // Continuous Integration mode + // if true, it capture browsers, run tests and exit + singleRun: true + }); +}; \ No newline at end of file diff --git a/dist/bower_components/angular-bootstrap-datetimepicker/src/css/datetimepicker.css b/dist/bower_components/angular-bootstrap-datetimepicker/src/css/datetimepicker.css new file mode 100644 index 000000000..8fa0a35b0 --- /dev/null +++ b/dist/bower_components/angular-bootstrap-datetimepicker/src/css/datetimepicker.css @@ -0,0 +1,364 @@ +/** + * @license angular-bootstrap-datetimepicker v0.2.2 + * (c) 2013 Knight Rider Consulting, Inc. http://www.knightrider.com + * License: MIT + */ + +.datetimepicker { + padding: 4px; + margin-top: 1px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + direction: ltr; + /*.dow { + border-top: 1px solid #ddd !important; + }*/ + +} +.datetimepicker-inline { + width: 220px; +} +.datetimepicker.datetimepicker-rtl { + direction: rtl; +} +.datetimepicker.datetimepicker-rtl table tr td span { + float: right; +} +.datetimepicker-dropdown, .datetimepicker-dropdown-left { + top: 0; + left: 0; +} +[class*=" datetimepicker-dropdown"]:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; +} +[class*=" datetimepicker-dropdown"]:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; +} +[class*=" datetimepicker-dropdown-top"]:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #ccc; + border-top-color: rgba(0, 0, 0, 0.2); + border-bottom: 0; +} +[class*=" datetimepicker-dropdown-top"]:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid #ffffff; + border-bottom: 0; +} +.datetimepicker-dropdown-bottom-left:before { + top: -7px; + right: 6px; +} +.datetimepicker-dropdown-bottom-left:after { + top: -6px; + right: 7px; +} +.datetimepicker-dropdown-bottom-right:before { + top: -7px; + left: 6px; +} +.datetimepicker-dropdown-bottom-right:after { + top: -6px; + left: 7px; +} +.datetimepicker-dropdown-top-left:before { + bottom: -7px; + right: 6px; +} +.datetimepicker-dropdown-top-left:after { + bottom: -6px; + right: 7px; +} +.datetimepicker-dropdown-top-right:before { + bottom: -7px; + left: 6px; +} +.datetimepicker-dropdown-top-right:after { + bottom: -6px; + left: 7px; +} +.datetimepicker > div { + display: none; +} +.datetimepicker.minutes div.datetimepicker-minutes { + display: block; +} +.datetimepicker.hours div.datetimepicker-hours { + display: block; +} +.datetimepicker.days div.datetimepicker-days { + display: block; +} +.datetimepicker.months div.datetimepicker-months { + display: block; +} +.datetimepicker.years div.datetimepicker-years { + display: block; +} +.datetimepicker table { + margin: 0; +} +.datetimepicker td, +.datetimepicker th { + text-align: center; + width: 20px; + height: 20px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + border: none; +} +.table-striped .datetimepicker table tr td, +.table-striped .datetimepicker table tr th { + background-color: transparent; +} +.datetimepicker table tr td.minute:hover { + background: #eeeeee; + cursor: pointer; +} +.datetimepicker table tr td.hour:hover { + background: #eeeeee; + cursor: pointer; +} +.datetimepicker table tr td.day:hover { + background: #eeeeee; + cursor: pointer; +} +.datetimepicker table tr td.past, +.datetimepicker table tr td.future { + color: #999999; +} +.datetimepicker table tr td.disabled, +.datetimepicker table tr td.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datetimepicker table tr td.today, +.datetimepicker table tr td.today:hover, +.datetimepicker table tr td.today.disabled, +.datetimepicker table tr td.today.disabled:hover { + background-color: #fde19a; + background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a)); + background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -o-linear-gradient(top, #fdd49a, #fdf59a); + background-image: linear-gradient(top, #fdd49a, #fdf59a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0); + border-color: #fdf59a #fdf59a #fbed50; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} +.datetimepicker table tr td.today:hover, +.datetimepicker table tr td.today:hover:hover, +.datetimepicker table tr td.today.disabled:hover, +.datetimepicker table tr td.today.disabled:hover:hover, +.datetimepicker table tr td.today:active, +.datetimepicker table tr td.today:hover:active, +.datetimepicker table tr td.today.disabled:active, +.datetimepicker table tr td.today.disabled:hover:active, +.datetimepicker table tr td.today.active, +.datetimepicker table tr td.today:hover.active, +.datetimepicker table tr td.today.disabled.active, +.datetimepicker table tr td.today.disabled:hover.active, +.datetimepicker table tr td.today.disabled, +.datetimepicker table tr td.today:hover.disabled, +.datetimepicker table tr td.today.disabled.disabled, +.datetimepicker table tr td.today.disabled:hover.disabled, +.datetimepicker table tr td.today[disabled], +.datetimepicker table tr td.today:hover[disabled], +.datetimepicker table tr td.today.disabled[disabled], +.datetimepicker table tr td.today.disabled:hover[disabled] { + background-color: #fdf59a; +} +.datetimepicker table tr td.today:active, +.datetimepicker table tr td.today:hover:active, +.datetimepicker table tr td.today.disabled:active, +.datetimepicker table tr td.today.disabled:hover:active, +.datetimepicker table tr td.today.active, +.datetimepicker table tr td.today:hover.active, +.datetimepicker table tr td.today.disabled.active, +.datetimepicker table tr td.today.disabled:hover.active { + background-color: #fbf069 \9; +} +.datetimepicker table tr td.active, +.datetimepicker table tr td.active:hover, +.datetimepicker table tr td.active.disabled, +.datetimepicker table tr td.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datetimepicker table tr td.active:hover, +.datetimepicker table tr td.active:hover:hover, +.datetimepicker table tr td.active.disabled:hover, +.datetimepicker table tr td.active.disabled:hover:hover, +.datetimepicker table tr td.active:active, +.datetimepicker table tr td.active:hover:active, +.datetimepicker table tr td.active.disabled:active, +.datetimepicker table tr td.active.disabled:hover:active, +.datetimepicker table tr td.active.active, +.datetimepicker table tr td.active:hover.active, +.datetimepicker table tr td.active.disabled.active, +.datetimepicker table tr td.active.disabled:hover.active, +.datetimepicker table tr td.active.disabled, +.datetimepicker table tr td.active:hover.disabled, +.datetimepicker table tr td.active.disabled.disabled, +.datetimepicker table tr td.active.disabled:hover.disabled, +.datetimepicker table tr td.active[disabled], +.datetimepicker table tr td.active:hover[disabled], +.datetimepicker table tr td.active.disabled[disabled], +.datetimepicker table tr td.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datetimepicker table tr td.active:active, +.datetimepicker table tr td.active:hover:active, +.datetimepicker table tr td.active.disabled:active, +.datetimepicker table tr td.active.disabled:hover:active, +.datetimepicker table tr td.active.active, +.datetimepicker table tr td.active:hover.active, +.datetimepicker table tr td.active.disabled.active, +.datetimepicker table tr td.active.disabled:hover.active { + background-color: #003399 \9; +} +.datetimepicker table tr td span { + display: block; + width: 23%; + height: 54px; + line-height: 54px; + float: left; + margin: 1%; + cursor: pointer; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.datetimepicker span.hour { + height: 26px; + line-height: 26px; +} +.datetimepicker .datetimepicker-hours table tr td span.hour_am, +.datetimepicker .datetimepicker-hours table tr td span.hour_pm { + width: 14.6%; +} +.datetimepicker .datetimepicker-hours fieldset legend, +.datetimepicker .datetimepicker-minutes fieldset legend { + margin-bottom: inherit; + line-height: 30px; +} +.datetimepicker span.minute { + height: 26px; + line-height: 26px; +} +.datetimepicker table tr td span:hover { + background: #eeeeee; +} +.datetimepicker table tr td span.disabled, +.datetimepicker table tr td span.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datetimepicker table tr td span.active, +.datetimepicker table tr td span.active:hover, +.datetimepicker table tr td span.active.disabled, +.datetimepicker table tr td span.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datetimepicker table tr td span.active:hover, +.datetimepicker table tr td span.active:hover:hover, +.datetimepicker table tr td span.active.disabled:hover, +.datetimepicker table tr td span.active.disabled:hover:hover, +.datetimepicker table tr td span.active:active, +.datetimepicker table tr td span.active:hover:active, +.datetimepicker table tr td span.active.disabled:active, +.datetimepicker table tr td span.active.disabled:hover:active, +.datetimepicker table tr td span.active.active, +.datetimepicker table tr td span.active:hover.active, +.datetimepicker table tr td span.active.disabled.active, +.datetimepicker table tr td span.active.disabled:hover.active, +.datetimepicker table tr td span.active.disabled, +.datetimepicker table tr td span.active:hover.disabled, +.datetimepicker table tr td span.active.disabled.disabled, +.datetimepicker table tr td span.active.disabled:hover.disabled, +.datetimepicker table tr td span.active[disabled], +.datetimepicker table tr td span.active:hover[disabled], +.datetimepicker table tr td span.active.disabled[disabled], +.datetimepicker table tr td span.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datetimepicker table tr td span.active:active, +.datetimepicker table tr td span.active:hover:active, +.datetimepicker table tr td span.active.disabled:active, +.datetimepicker table tr td span.active.disabled:hover:active, +.datetimepicker table tr td span.active.active, +.datetimepicker table tr td span.active:hover.active, +.datetimepicker table tr td span.active.disabled.active, +.datetimepicker table tr td span.active.disabled:hover.active { + background-color: #003399 \9; +} +.datetimepicker table tr td span.past, +.datetimepicker table tr td span.future { + color: #999999; +} +.datetimepicker th.switch { + width: 145px; +} +.datetimepicker thead tr:first-child th, +.datetimepicker tfoot tr:first-child th { + cursor: pointer; +} +.datetimepicker thead tr:first-child th:hover, +.datetimepicker tfoot tr:first-child th:hover { + background: #eeeeee; +} +.input-append.date .add-on i, +.input-prepend.date .add-on i { + cursor: pointer; + width: 14px; + height: 14px; +} \ No newline at end of file diff --git a/dist/bower_components/angular-bootstrap-datetimepicker/src/js/datetimepicker.js b/dist/bower_components/angular-bootstrap-datetimepicker/src/js/datetimepicker.js new file mode 100644 index 000000000..5ccffebb0 --- /dev/null +++ b/dist/bower_components/angular-bootstrap-datetimepicker/src/js/datetimepicker.js @@ -0,0 +1,341 @@ +/*globals angular, moment, jQuery */ +/*jslint vars:true */ + +/** + * @license angular-bootstrap-datetimepicker v0.2.2 + * (c) 2013 Knight Rider Consulting, Inc. http://www.knightrider.com + * License: MIT + */ + +/** + * + * @author Dale "Ducky" Lotts + * @since 2013-Jul-8 + */ + +angular.module('ui.bootstrap.datetimepicker', []) + .constant('dateTimePickerConfig', { + dropdownSelector: null, + minuteStep: 5, + minView: 'minute', + startView: 'day', + weekStart: 0 + }) + .constant('dateTimePickerConfigValidation', function (configuration) { + "use strict"; + + var validOptions = ['startView', 'minView', 'minuteStep', 'dropdownSelector', 'weekStart']; + + for (var prop in configuration) { + if (configuration.hasOwnProperty(prop)) { + if (validOptions.indexOf(prop) < 0) { + throw ("invalid option: " + prop); + } + } + } + + // Order of the elements in the validViews array is significant. + var validViews = ['minute', 'hour', 'day', 'month', 'year']; + + if (validViews.indexOf(configuration.startView) < 0) { + throw ("invalid startView value: " + configuration.startView); + } + + if (validViews.indexOf(configuration.minView) < 0) { + throw ("invalid minView value: " + configuration.minView); + } + + if (validViews.indexOf(configuration.minView) > validViews.indexOf(configuration.startView)) { + throw ("startView must be greater than minView"); + } + + if (!angular.isNumber(configuration.minuteStep)) { + throw ("minuteStep must be numeric"); + } + if (configuration.minuteStep <= 0 || configuration.minuteStep >= 60) { + throw ("minuteStep must be greater than zero and less than 60"); + } + if (configuration.dropdownSelector !== null && !angular.isString(configuration.dropdownSelector)) { + throw ("dropdownSelector must be a string"); + } + + if (!angular.isNumber(configuration.weekStart)) { + throw ("weekStart must be numeric"); + } + if (configuration.weekStart < 0 || configuration.weekStart > 6) { + throw ("weekStart must be greater than or equal to zero and less than 7"); + } + } +) + .directive('datetimepicker', ['dateTimePickerConfig', 'dateTimePickerConfigValidation', function (defaultConfig, validateConfigurationFunction) { + "use strict"; + + return { + restrict: 'E', + require: 'ngModel', + template: "
" + + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + ' ' + + " " + + " " + + ' ' + + " " + + " " + + " " + + "
{{ data.title }}
{{ day }}
" + + " {{ dateValue.display }} " + + "
{{ dateValue.display }}
", + scope: { + ngModel: "=", + onSetTime: "=" + }, + replace: true, + link: function (scope, element, attrs) { + + var directiveConfig = {}; + + if (attrs.datetimepickerConfig) { + directiveConfig = scope.$eval(attrs.datetimepickerConfig); + } + + var configuration = {}; + + angular.extend(configuration, defaultConfig, directiveConfig); + + validateConfigurationFunction(configuration); + + var dataFactory = { + year: function (unixDate) { + var selectedDate = moment.utc(unixDate).startOf('year'); + // View starts one year before the decade starts and ends one year after the decade ends + // i.e. passing in a date of 1/1/2013 will give a range of 2009 to 2020 + // Truncate the last digit from the current year and subtract 1 to get the start of the decade + var startDecade = (parseInt(selectedDate.year() / 10, 10) * 10); + var startDate = moment.utc(selectedDate).year(startDecade - 1).startOf('year'); + var activeYear = scope.ngModel ? moment(scope.ngModel).year() : 0; + + var result = { + 'currentView': 'year', + 'nextView': configuration.minView === 'year' ? 'setTime' : 'month', + 'title': startDecade + '-' + (startDecade + 9), + 'leftDate': moment.utc(startDate).subtract(9, 'year').valueOf(), + 'rightDate': moment.utc(startDate).add(11, 'year').valueOf(), + 'dates': [] + }; + + for (var i = 0; i < 12; i++) { + var yearMoment = moment.utc(startDate).add(i, 'years'); + var dateValue = { + 'date': yearMoment.valueOf(), + 'display': yearMoment.format('YYYY'), + 'past': yearMoment.year() < startDecade, + 'future': yearMoment.year() > startDecade + 9, + 'active': yearMoment.year() === activeYear + }; + + result.dates.push(dateValue); + } + + return result; + }, + + month: function (unixDate) { + + var startDate = moment.utc(unixDate).startOf('year'); + + var activeDate = scope.ngModel ? moment(scope.ngModel).format('YYYY-MMM') : 0; + + var result = { + 'previousView': 'year', + 'currentView': 'month', + 'nextView': configuration.minView === 'month' ? 'setTime' : 'day', + 'currentDate': startDate.valueOf(), + 'title': startDate.format('YYYY'), + 'leftDate': moment.utc(startDate).subtract(1, 'year').valueOf(), + 'rightDate': moment.utc(startDate).add(1, 'year').valueOf(), + 'dates': [] + }; + + for (var i = 0; i < 12; i++) { + var monthMoment = moment.utc(startDate).add(i, 'months'); + var dateValue = { + 'date': monthMoment.valueOf(), + 'display': monthMoment.format('MMM'), + 'active': monthMoment.format('YYYY-MMM') === activeDate + }; + + result.dates.push(dateValue); + } + + return result; + }, + + day: function (unixDate) { + + var selectedDate = moment.utc(unixDate); + var startOfMonth = moment.utc(selectedDate).startOf('month'); + var endOfMonth = moment.utc(selectedDate).endOf('month'); + + var startDate = moment.utc(startOfMonth).subtract(startOfMonth.weekday() - configuration.weekStart, 'days'); + + var activeDate = scope.ngModel ? moment(scope.ngModel).format('YYYY-MMM-DD') : ''; + + var result = { + 'previousView': 'month', + 'currentView': 'day', + 'nextView': configuration.minView === 'day' ? 'setTime' : 'hour', + 'currentDate': selectedDate.valueOf(), + 'title': selectedDate.format('YYYY-MMM'), + 'leftDate': moment.utc(startOfMonth).subtract(1, 'months').valueOf(), + 'rightDate': moment.utc(startOfMonth).add(1, 'months').valueOf(), + 'dayNames': [], + 'weeks': [] + }; + + + for (var dayNumber = configuration.weekStart; dayNumber < configuration.weekStart + 7; dayNumber++) { + result.dayNames.push(moment.utc().weekday(dayNumber).format('dd')); + } + + for (var i = 0; i < 6; i++) { + var week = { dates: [] }; + for (var j = 0; j < 7; j++) { + var monthMoment = moment.utc(startDate).add((i * 7) + j, 'days'); + var dateValue = { + 'date': monthMoment.valueOf(), + 'display': monthMoment.format('D'), + 'active': monthMoment.format('YYYY-MMM-DD') === activeDate, + 'past': monthMoment.isBefore(startOfMonth), + 'future': monthMoment.isAfter(endOfMonth) + }; + week.dates.push(dateValue); + } + result.weeks.push(week); + } + + return result; + }, + + hour: function (unixDate) { + var selectedDate = moment.utc(unixDate).hour(0).minute(0).second(0); + + var activeFormat = scope.ngModel ? moment(scope.ngModel).format('YYYY-MM-DD H') : ''; + + var result = { + 'previousView': 'day', + 'currentView': 'hour', + 'nextView': configuration.minView === 'hour' ? 'setTime' : 'minute', + 'currentDate': selectedDate.valueOf(), + 'title': selectedDate.format('YYYY-MMM-DD'), + 'leftDate': moment.utc(selectedDate).subtract(1, 'days').valueOf(), + 'rightDate': moment.utc(selectedDate).add(1, 'days').valueOf(), + 'dates': [] + }; + + for (var i = 0; i < 24; i++) { + var hourMoment = moment.utc(selectedDate).add(i, 'hours'); + var dateValue = { + 'date': hourMoment.valueOf(), + 'display': hourMoment.format('H:00'), + 'active': hourMoment.format('YYYY-MM-DD H') === activeFormat + }; + + result.dates.push(dateValue); + } + + return result; + }, + + minute: function (unixDate) { + var selectedDate = moment.utc(unixDate).minute(0).second(0); + + var activeFormat = scope.ngModel ? moment(scope.ngModel).format('YYYY-MM-DD H:mm') : ''; + + var result = { + 'previousView': 'hour', + 'currentView': 'minute', + 'nextView': 'setTime', + 'currentDate': selectedDate.valueOf(), + 'title': selectedDate.format('YYYY-MMM-DD H:mm'), + 'leftDate': moment.utc(selectedDate).subtract(1, 'hours').valueOf(), + 'rightDate': moment.utc(selectedDate).add(1, 'hours').valueOf(), + 'dates': [] + }; + + var limit = 60 / configuration.minuteStep; + + for (var i = 0; i < limit; i++) { + var hourMoment = moment.utc(selectedDate).add(i * configuration.minuteStep, 'minute'); + var dateValue = { + 'date': hourMoment.valueOf(), + 'display': hourMoment.format('H:mm'), + 'active': hourMoment.format('YYYY-MM-DD H:mm') === activeFormat + }; + + result.dates.push(dateValue); + } + + return result; + }, + + setTime: function (unixDate) { + var tempDate = new Date(unixDate); + var newDate = new Date(tempDate.getTime() + (tempDate.getTimezoneOffset() * 60000)); + if (configuration.dropdownSelector) { + jQuery(configuration.dropdownSelector).dropdown('toggle'); + } + if (angular.isFunction(scope.onSetTime)) { + scope.onSetTime(newDate, scope.ngModel); + } + scope.ngModel = newDate; + return dataFactory[scope.data.currentView](unixDate); + } + }; + + var getUTCTime = function () { + var tempDate = (scope.ngModel ? moment(scope.ngModel).toDate() : new Date()); + return tempDate.getTime() - (tempDate.getTimezoneOffset() * 60000); + }; + + scope.changeView = function (viewName, unixDate, event) { + if (event) { + event.stopPropagation(); + event.preventDefault(); + } + + if (viewName && (unixDate > -Infinity) && dataFactory[viewName]) { + scope.data = dataFactory[viewName](unixDate); + } + }; + + scope.changeView(configuration.startView, getUTCTime()); + + scope.$watch('ngModel', function () { + scope.changeView(scope.data.currentView, getUTCTime()); + }); + } + }; + }]); \ No newline at end of file diff --git a/dist/bower_components/angular-bootstrap/.bower.json b/dist/bower_components/angular-bootstrap/.bower.json new file mode 100644 index 000000000..03c633a71 --- /dev/null +++ b/dist/bower_components/angular-bootstrap/.bower.json @@ -0,0 +1,23 @@ +{ + "author": { + "name": "https://github.com/angular-ui/bootstrap/graphs/contributors" + }, + "name": "angular-bootstrap", + "version": "0.10.0", + "main": [ + "./ui-bootstrap-tpls.js" + ], + "dependencies": { + "angular": ">=1" + }, + "homepage": "https://github.com/angular-ui/bootstrap-bower", + "_release": "0.10.0", + "_resolution": { + "type": "version", + "tag": "0.10.0", + "commit": "f486d33d6f4c60d905ed0792eacbba2456a32b87" + }, + "_source": "git://github.com/angular-ui/bootstrap-bower.git", + "_target": "0.10.0", + "_originalSource": "angular-bootstrap" +} \ No newline at end of file diff --git a/dist/bower_components/angular-bootstrap/bower.json b/dist/bower_components/angular-bootstrap/bower.json new file mode 100644 index 000000000..dd5536c42 --- /dev/null +++ b/dist/bower_components/angular-bootstrap/bower.json @@ -0,0 +1,11 @@ +{ + "author": { + "name": "https://github.com/angular-ui/bootstrap/graphs/contributors" + }, + "name": "angular-bootstrap", + "version": "0.10.0", + "main": ["./ui-bootstrap-tpls.js"], + "dependencies": { + "angular": ">=1" + } +} diff --git a/dist/bower_components/angular-bootstrap/ui-bootstrap-tpls.js b/dist/bower_components/angular-bootstrap/ui-bootstrap-tpls.js new file mode 100644 index 000000000..cfec6be9e --- /dev/null +++ b/dist/bower_components/angular-bootstrap/ui-bootstrap-tpls.js @@ -0,0 +1,3677 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.10.0 - 2014-01-13 + * License: MIT + */ +angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]); +angular.module("ui.bootstrap.tpls", ["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/popup.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]); +angular.module('ui.bootstrap.transition', []) + +/** + * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete. + * @param {DOMElement} element The DOMElement that will be animated. + * @param {string|object|function} trigger The thing that will cause the transition to start: + * - As a string, it represents the css class to be added to the element. + * - As an object, it represents a hash of style attributes to be applied to the element. + * - As a function, it represents a function to be called that will cause the transition to occur. + * @return {Promise} A promise that is resolved when the transition finishes. + */ +.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) { + + var $transition = function(element, trigger, options) { + options = options || {}; + var deferred = $q.defer(); + var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"]; + + var transitionEndHandler = function(event) { + $rootScope.$apply(function() { + element.unbind(endEventName, transitionEndHandler); + deferred.resolve(element); + }); + }; + + if (endEventName) { + element.bind(endEventName, transitionEndHandler); + } + + // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur + $timeout(function() { + if ( angular.isString(trigger) ) { + element.addClass(trigger); + } else if ( angular.isFunction(trigger) ) { + trigger(element); + } else if ( angular.isObject(trigger) ) { + element.css(trigger); + } + //If browser does not support transitions, instantly resolve + if ( !endEventName ) { + deferred.resolve(element); + } + }); + + // Add our custom cancel function to the promise that is returned + // We can call this if we are about to run a new transition, which we know will prevent this transition from ending, + // i.e. it will therefore never raise a transitionEnd event for that transition + deferred.promise.cancel = function() { + if ( endEventName ) { + element.unbind(endEventName, transitionEndHandler); + } + deferred.reject('Transition cancelled'); + }; + + return deferred.promise; + }; + + // Work out the name of the transitionEnd event + var transElement = document.createElement('trans'); + var transitionEndEventNames = { + 'WebkitTransition': 'webkitTransitionEnd', + 'MozTransition': 'transitionend', + 'OTransition': 'oTransitionEnd', + 'transition': 'transitionend' + }; + var animationEndEventNames = { + 'WebkitTransition': 'webkitAnimationEnd', + 'MozTransition': 'animationend', + 'OTransition': 'oAnimationEnd', + 'transition': 'animationend' + }; + function findEndEventName(endEventNames) { + for (var name in endEventNames){ + if (transElement.style[name] !== undefined) { + return endEventNames[name]; + } + } + } + $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); + $transition.animationEndEventName = findEndEventName(animationEndEventNames); + return $transition; +}]); + +angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition']) + + .directive('collapse', ['$transition', function ($transition, $timeout) { + + return { + link: function (scope, element, attrs) { + + var initialAnimSkip = true; + var currentTransition; + + function doTransition(change) { + var newTransition = $transition(element, change); + if (currentTransition) { + currentTransition.cancel(); + } + currentTransition = newTransition; + newTransition.then(newTransitionDone, newTransitionDone); + return newTransition; + + function newTransitionDone() { + // Make sure it's this transition, otherwise, leave it alone. + if (currentTransition === newTransition) { + currentTransition = undefined; + } + } + } + + function expand() { + if (initialAnimSkip) { + initialAnimSkip = false; + expandDone(); + } else { + element.removeClass('collapse').addClass('collapsing'); + doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone); + } + } + + function expandDone() { + element.removeClass('collapsing'); + element.addClass('collapse in'); + element.css({height: 'auto'}); + } + + function collapse() { + if (initialAnimSkip) { + initialAnimSkip = false; + collapseDone(); + element.css({height: 0}); + } else { + // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value + element.css({ height: element[0].scrollHeight + 'px' }); + //trigger reflow so a browser realizes that height was updated from auto to a specific value + var x = element[0].offsetWidth; + + element.removeClass('collapse in').addClass('collapsing'); + + doTransition({ height: 0 }).then(collapseDone); + } + } + + function collapseDone() { + element.removeClass('collapsing'); + element.addClass('collapse'); + } + + scope.$watch(attrs.collapse, function (shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); + } + }; + }]); + +angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) + +.constant('accordionConfig', { + closeOthers: true +}) + +.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) { + + // This array keeps track of the accordion groups + this.groups = []; + + // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to + this.closeOthers = function(openGroup) { + var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; + if ( closeOthers ) { + angular.forEach(this.groups, function (group) { + if ( group !== openGroup ) { + group.isOpen = false; + } + }); + } + }; + + // This is called from the accordion-group directive to add itself to the accordion + this.addGroup = function(groupScope) { + var that = this; + this.groups.push(groupScope); + + groupScope.$on('$destroy', function (event) { + that.removeGroup(groupScope); + }); + }; + + // This is called from the accordion-group directive when to remove itself + this.removeGroup = function(group) { + var index = this.groups.indexOf(group); + if ( index !== -1 ) { + this.groups.splice(this.groups.indexOf(group), 1); + } + }; + +}]) + +// The accordion directive simply sets up the directive controller +// and adds an accordion CSS class to itself element. +.directive('accordion', function () { + return { + restrict:'EA', + controller:'AccordionController', + transclude: true, + replace: false, + templateUrl: 'template/accordion/accordion.html' + }; +}) + +// The accordion-group directive indicates a block of html that will expand and collapse in an accordion +.directive('accordionGroup', ['$parse', function($parse) { + return { + require:'^accordion', // We need this directive to be inside an accordion + restrict:'EA', + transclude:true, // It transcludes the contents of the directive into the template + replace: true, // The element containing the directive will be replaced with the template + templateUrl:'template/accordion/accordion-group.html', + scope:{ heading:'@' }, // Create an isolated scope and interpolate the heading attribute onto this scope + controller: function() { + this.setHeading = function(element) { + this.heading = element; + }; + }, + link: function(scope, element, attrs, accordionCtrl) { + var getIsOpen, setIsOpen; + + accordionCtrl.addGroup(scope); + + scope.isOpen = false; + + if ( attrs.isOpen ) { + getIsOpen = $parse(attrs.isOpen); + setIsOpen = getIsOpen.assign; + + scope.$parent.$watch(getIsOpen, function(value) { + scope.isOpen = !!value; + }); + } + + scope.$watch('isOpen', function(value) { + if ( value ) { + accordionCtrl.closeOthers(scope); + } + if ( setIsOpen ) { + setIsOpen(scope.$parent, value); + } + }); + } + }; +}]) + +// Use accordion-heading below an accordion-group to provide a heading containing HTML +// +// Heading containing HTML - +// +.directive('accordionHeading', function() { + return { + restrict: 'EA', + transclude: true, // Grab the contents to be used as the heading + template: '', // In effect remove this element! + replace: true, + require: '^accordionGroup', + compile: function(element, attr, transclude) { + return function link(scope, element, attr, accordionGroupCtrl) { + // Pass the heading to the accordion-group controller + // so that it can be transcluded into the right place in the template + // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat] + accordionGroupCtrl.setHeading(transclude(scope, function() {})); + }; + } + }; +}) + +// Use in the accordion-group template to indicate where you want the heading to be transcluded +// You must provide the property on the accordion-group controller that will hold the transcluded element +//
+// +// ... +//
+.directive('accordionTransclude', function() { + return { + require: '^accordionGroup', + link: function(scope, element, attr, controller) { + scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) { + if ( heading ) { + element.html(''); + element.append(heading); + } + }); + } + }; +}); + +angular.module("ui.bootstrap.alert", []) + +.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) { + $scope.closeable = 'close' in $attrs; +}]) + +.directive('alert', function () { + return { + restrict:'EA', + controller:'AlertController', + templateUrl:'template/alert/alert.html', + transclude:true, + replace:true, + scope: { + type: '=', + close: '&' + } + }; +}); + +angular.module('ui.bootstrap.bindHtml', []) + + .directive('bindHtmlUnsafe', function () { + return function (scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ''); + }); + }; + }); +angular.module('ui.bootstrap.buttons', []) + +.constant('buttonConfig', { + activeClass: 'active', + toggleEvent: 'click' +}) + +.controller('ButtonsController', ['buttonConfig', function(buttonConfig) { + this.activeClass = buttonConfig.activeClass || 'active'; + this.toggleEvent = buttonConfig.toggleEvent || 'click'; +}]) + +.directive('btnRadio', function () { + return { + require: ['btnRadio', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + if (!element.hasClass(buttonsCtrl.activeClass)) { + scope.$apply(function () { + ngModelCtrl.$setViewValue(scope.$eval(attrs.btnRadio)); + ngModelCtrl.$render(); + }); + } + }); + } + }; +}) + +.directive('btnCheckbox', function () { + return { + require: ['btnCheckbox', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + function getTrueValue() { + return getCheckboxValue(attrs.btnCheckboxTrue, true); + } + + function getFalseValue() { + return getCheckboxValue(attrs.btnCheckboxFalse, false); + } + + function getCheckboxValue(attributeValue, defaultValue) { + var val = scope.$eval(attributeValue); + return angular.isDefined(val) ? val : defaultValue; + } + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + scope.$apply(function () { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); + }); + }); + } + }; +}); + +/** +* @ngdoc overview +* @name ui.bootstrap.carousel +* +* @description +* AngularJS version of an image carousel. +* +*/ +angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) +.controller('CarouselController', ['$scope', '$timeout', '$transition', '$q', function ($scope, $timeout, $transition, $q) { + var self = this, + slides = self.slides = [], + currentIndex = -1, + currentTimeout, isPlaying; + self.currentSlide = null; + + var destroyed = false; + /* direction: "prev" or "next" */ + self.select = function(nextSlide, direction) { + var nextIndex = slides.indexOf(nextSlide); + //Decide direction if it's not given + if (direction === undefined) { + direction = nextIndex > currentIndex ? "next" : "prev"; + } + if (nextSlide && nextSlide !== self.currentSlide) { + if ($scope.$currentTransition) { + $scope.$currentTransition.cancel(); + //Timeout so ng-class in template has time to fix classes for finished slide + $timeout(goNext); + } else { + goNext(); + } + } + function goNext() { + // Scope has been destroyed, stop here. + if (destroyed) { return; } + //If we have a slide to transition from and we have a transition type and we're allowed, go + if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) { + //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime + nextSlide.$element.addClass(direction); + var reflow = nextSlide.$element[0].offsetWidth; //force reflow + + //Set all other slides to stop doing their stuff for the new transition + angular.forEach(slides, function(slide) { + angular.extend(slide, {direction: '', entering: false, leaving: false, active: false}); + }); + angular.extend(nextSlide, {direction: direction, active: true, entering: true}); + angular.extend(self.currentSlide||{}, {direction: direction, leaving: true}); + + $scope.$currentTransition = $transition(nextSlide.$element, {}); + //We have to create new pointers inside a closure since next & current will change + (function(next,current) { + $scope.$currentTransition.then( + function(){ transitionDone(next, current); }, + function(){ transitionDone(next, current); } + ); + }(nextSlide, self.currentSlide)); + } else { + transitionDone(nextSlide, self.currentSlide); + } + self.currentSlide = nextSlide; + currentIndex = nextIndex; + //every time you change slides, reset the timer + restartTimer(); + } + function transitionDone(next, current) { + angular.extend(next, {direction: '', active: true, leaving: false, entering: false}); + angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false}); + $scope.$currentTransition = null; + } + }; + $scope.$on('$destroy', function () { + destroyed = true; + }); + + /* Allow outside people to call indexOf on slides array */ + self.indexOfSlide = function(slide) { + return slides.indexOf(slide); + }; + + $scope.next = function() { + var newIndex = (currentIndex + 1) % slides.length; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(slides[newIndex], 'next'); + } + }; + + $scope.prev = function() { + var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(slides[newIndex], 'prev'); + } + }; + + $scope.select = function(slide) { + self.select(slide); + }; + + $scope.isActive = function(slide) { + return self.currentSlide === slide; + }; + + $scope.slides = function() { + return slides; + }; + + $scope.$watch('interval', restartTimer); + $scope.$on('$destroy', resetTimer); + + function restartTimer() { + resetTimer(); + var interval = +$scope.interval; + if (!isNaN(interval) && interval>=0) { + currentTimeout = $timeout(timerFn, interval); + } + } + + function resetTimer() { + if (currentTimeout) { + $timeout.cancel(currentTimeout); + currentTimeout = null; + } + } + + function timerFn() { + if (isPlaying) { + $scope.next(); + restartTimer(); + } else { + $scope.pause(); + } + } + + $scope.play = function() { + if (!isPlaying) { + isPlaying = true; + restartTimer(); + } + }; + $scope.pause = function() { + if (!$scope.noPause) { + isPlaying = false; + resetTimer(); + } + }; + + self.addSlide = function(slide, element) { + slide.$element = element; + slides.push(slide); + //if this is the first slide or the slide is set to active, select it + if(slides.length === 1 || slide.active) { + self.select(slides[slides.length-1]); + if (slides.length == 1) { + $scope.play(); + } + } else { + slide.active = false; + } + }; + + self.removeSlide = function(slide) { + //get the index of the slide inside the carousel + var index = slides.indexOf(slide); + slides.splice(index, 1); + if (slides.length > 0 && slide.active) { + if (index >= slides.length) { + self.select(slides[index-1]); + } else { + self.select(slides[index]); + } + } else if (currentIndex > index) { + currentIndex--; + } + }; + +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:carousel + * @restrict EA + * + * @description + * Carousel is the outer container for a set of image 'slides' to showcase. + * + * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide. + * @param {boolean=} noTransition Whether to disable transitions on the carousel. + * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover). + * + * @example + + + + + + + + + + + + + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + + + */ +.directive('carousel', [function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + controller: 'CarouselController', + require: 'carousel', + templateUrl: 'template/carousel/carousel.html', + scope: { + interval: '=', + noTransition: '=', + noPause: '=' + } + }; +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:slide + * @restrict EA + * + * @description + * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}. Must be placed as a child of a carousel element. + * + * @param {boolean=} active Model binding, whether or not this slide is currently active. + * + * @example + + +
+ + + + + + +
+
+
    +
  • + + {{$index}}: {{slide.text}} +
  • +
+ Add Slide +
+
+ Interval, in milliseconds: +
Enter a negative number to stop the interval. +
+
+
+
+ +function CarouselDemoCtrl($scope) { + $scope.myInterval = 5000; + var slides = $scope.slides = []; + $scope.addSlide = function() { + var newWidth = 200 + ((slides.length + (25 * slides.length)) % 150); + slides.push({ + image: 'http://placekitten.com/' + newWidth + '/200', + text: ['More','Extra','Lots of','Surplus'][slides.length % 4] + ' ' + ['Cats', 'Kittys', 'Felines', 'Cutes'][slides.length % 4] + }); + }; + for (var i=0; i<4; i++) $scope.addSlide(); +} + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + +
+*/ + +.directive('slide', ['$parse', function($parse) { + return { + require: '^carousel', + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'template/carousel/slide.html', + scope: { + }, + link: function (scope, element, attrs, carouselCtrl) { + //Set up optional 'active' = binding + if (attrs.active) { + var getActive = $parse(attrs.active); + var setActive = getActive.assign; + var lastValue = scope.active = getActive(scope.$parent); + scope.$watch(function parentActiveWatch() { + var parentActive = getActive(scope.$parent); + + if (parentActive !== scope.active) { + // we are out of sync and need to copy + if (parentActive !== lastValue) { + // parent changed and it has precedence + lastValue = scope.active = parentActive; + } else { + // if the parent can be assigned then do so + setActive(scope.$parent, parentActive = lastValue = scope.active); + } + } + return parentActive; + }); + } + + carouselCtrl.addSlide(scope, element); + //when the scope is destroyed then remove the slide from the current slides array + scope.$on('$destroy', function() { + carouselCtrl.removeSlide(scope); + }); + + scope.$watch('active', function(active) { + if (active) { + carouselCtrl.select(scope); + } + }); + } + }; +}]); + +angular.module('ui.bootstrap.position', []) + +/** + * A set of utility methods that can be use to retrieve position of DOM elements. + * It is meant to be used where we need to absolute-position DOM elements in + * relation to other, existing elements (this is the case for tooltips, popovers, + * typeahead suggestions etc.). + */ + .factory('$position', ['$document', '$window', function ($document, $window) { + + function getStyle(el, cssprop) { + if (el.currentStyle) { //IE + return el.currentStyle[cssprop]; + } else if ($window.getComputedStyle) { + return $window.getComputedStyle(el)[cssprop]; + } + // finally try and get inline style + return el.style[cssprop]; + } + + /** + * Checks if a given element is statically positioned + * @param element - raw DOM element + */ + function isStaticPositioned(element) { + return (getStyle(element, "position") || 'static' ) === 'static'; + } + + /** + * returns the closest, non-statically positioned parentOffset of a given element + * @param element + */ + var parentOffsetEl = function (element) { + var docDomEl = $document[0]; + var offsetParent = element.offsetParent || docDomEl; + while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docDomEl; + }; + + return { + /** + * Provides read-only equivalent of jQuery's position function: + * http://api.jquery.com/position/ + */ + position: function (element) { + var elBCR = this.offset(element); + var offsetParentBCR = { top: 0, left: 0 }; + var offsetParentEl = parentOffsetEl(element[0]); + if (offsetParentEl != $document[0]) { + offsetParentBCR = this.offset(angular.element(offsetParentEl)); + offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; + offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; + } + + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: elBCR.top - offsetParentBCR.top, + left: elBCR.left - offsetParentBCR.left + }; + }, + + /** + * Provides read-only equivalent of jQuery's offset function: + * http://api.jquery.com/offset/ + */ + offset: function (element) { + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft) + }; + } + }; + }]); + +angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position']) + +.constant('datepickerConfig', { + dayFormat: 'dd', + monthFormat: 'MMMM', + yearFormat: 'yyyy', + dayHeaderFormat: 'EEE', + dayTitleFormat: 'MMMM yyyy', + monthTitleFormat: 'yyyy', + showWeeks: true, + startingDay: 0, + yearRange: 20, + minDate: null, + maxDate: null +}) + +.controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) { + var format = { + day: getValue($attrs.dayFormat, dtConfig.dayFormat), + month: getValue($attrs.monthFormat, dtConfig.monthFormat), + year: getValue($attrs.yearFormat, dtConfig.yearFormat), + dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat), + dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat), + monthTitle: getValue($attrs.monthTitleFormat, dtConfig.monthTitleFormat) + }, + startingDay = getValue($attrs.startingDay, dtConfig.startingDay), + yearRange = getValue($attrs.yearRange, dtConfig.yearRange); + + this.minDate = dtConfig.minDate ? new Date(dtConfig.minDate) : null; + this.maxDate = dtConfig.maxDate ? new Date(dtConfig.maxDate) : null; + + function getValue(value, defaultValue) { + return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue; + } + + function getDaysInMonth( year, month ) { + return new Date(year, month, 0).getDate(); + } + + function getDates(startDate, n) { + var dates = new Array(n); + var current = startDate, i = 0; + while (i < n) { + dates[i++] = new Date(current); + current.setDate( current.getDate() + 1 ); + } + return dates; + } + + function makeDate(date, format, isSelected, isSecondary) { + return { date: date, label: dateFilter(date, format), selected: !!isSelected, secondary: !!isSecondary }; + } + + this.modes = [ + { + name: 'day', + getVisibleDates: function(date, selected) { + var year = date.getFullYear(), month = date.getMonth(), firstDayOfMonth = new Date(year, month, 1); + var difference = startingDay - firstDayOfMonth.getDay(), + numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference, + firstDate = new Date(firstDayOfMonth), numDates = 0; + + if ( numDisplayedFromPreviousMonth > 0 ) { + firstDate.setDate( - numDisplayedFromPreviousMonth + 1 ); + numDates += numDisplayedFromPreviousMonth; // Previous + } + numDates += getDaysInMonth(year, month + 1); // Current + numDates += (7 - numDates % 7) % 7; // Next + + var days = getDates(firstDate, numDates), labels = new Array(7); + for (var i = 0; i < numDates; i ++) { + var dt = new Date(days[i]); + days[i] = makeDate(dt, format.day, (selected && selected.getDate() === dt.getDate() && selected.getMonth() === dt.getMonth() && selected.getFullYear() === dt.getFullYear()), dt.getMonth() !== month); + } + for (var j = 0; j < 7; j++) { + labels[j] = dateFilter(days[j].date, format.dayHeader); + } + return { objects: days, title: dateFilter(date, format.dayTitle), labels: labels }; + }, + compare: function(date1, date2) { + return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) ); + }, + split: 7, + step: { months: 1 } + }, + { + name: 'month', + getVisibleDates: function(date, selected) { + var months = new Array(12), year = date.getFullYear(); + for ( var i = 0; i < 12; i++ ) { + var dt = new Date(year, i, 1); + months[i] = makeDate(dt, format.month, (selected && selected.getMonth() === i && selected.getFullYear() === year)); + } + return { objects: months, title: dateFilter(date, format.monthTitle) }; + }, + compare: function(date1, date2) { + return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() ); + }, + split: 3, + step: { years: 1 } + }, + { + name: 'year', + getVisibleDates: function(date, selected) { + var years = new Array(yearRange), year = date.getFullYear(), startYear = parseInt((year - 1) / yearRange, 10) * yearRange + 1; + for ( var i = 0; i < yearRange; i++ ) { + var dt = new Date(startYear + i, 0, 1); + years[i] = makeDate(dt, format.year, (selected && selected.getFullYear() === dt.getFullYear())); + } + return { objects: years, title: [years[0].label, years[yearRange - 1].label].join(' - ') }; + }, + compare: function(date1, date2) { + return date1.getFullYear() - date2.getFullYear(); + }, + split: 5, + step: { years: yearRange } + } + ]; + + this.isDisabled = function(date, mode) { + var currentMode = this.modes[mode || 0]; + return ((this.minDate && currentMode.compare(date, this.minDate) < 0) || (this.maxDate && currentMode.compare(date, this.maxDate) > 0) || ($scope.dateDisabled && $scope.dateDisabled({date: date, mode: currentMode.name}))); + }; +}]) + +.directive( 'datepicker', ['dateFilter', '$parse', 'datepickerConfig', '$log', function (dateFilter, $parse, datepickerConfig, $log) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/datepicker.html', + scope: { + dateDisabled: '&' + }, + require: ['datepicker', '?^ngModel'], + controller: 'DatepickerController', + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0], ngModel = ctrls[1]; + + if (!ngModel) { + return; // do nothing if no ng-model + } + + // Configuration parameters + var mode = 0, selected = new Date(), showWeeks = datepickerConfig.showWeeks; + + if (attrs.showWeeks) { + scope.$parent.$watch($parse(attrs.showWeeks), function(value) { + showWeeks = !! value; + updateShowWeekNumbers(); + }); + } else { + updateShowWeekNumbers(); + } + + if (attrs.min) { + scope.$parent.$watch($parse(attrs.min), function(value) { + datepickerCtrl.minDate = value ? new Date(value) : null; + refill(); + }); + } + if (attrs.max) { + scope.$parent.$watch($parse(attrs.max), function(value) { + datepickerCtrl.maxDate = value ? new Date(value) : null; + refill(); + }); + } + + function updateShowWeekNumbers() { + scope.showWeekNumbers = mode === 0 && showWeeks; + } + + // Split array into smaller arrays + function split(arr, size) { + var arrays = []; + while (arr.length > 0) { + arrays.push(arr.splice(0, size)); + } + return arrays; + } + + function refill( updateSelected ) { + var date = null, valid = true; + + if ( ngModel.$modelValue ) { + date = new Date( ngModel.$modelValue ); + + if ( isNaN(date) ) { + valid = false; + $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else if ( updateSelected ) { + selected = date; + } + } + ngModel.$setValidity('date', valid); + + var currentMode = datepickerCtrl.modes[mode], data = currentMode.getVisibleDates(selected, date); + angular.forEach(data.objects, function(obj) { + obj.disabled = datepickerCtrl.isDisabled(obj.date, mode); + }); + + ngModel.$setValidity('date-disabled', (!date || !datepickerCtrl.isDisabled(date))); + + scope.rows = split(data.objects, currentMode.split); + scope.labels = data.labels || []; + scope.title = data.title; + } + + function setMode(value) { + mode = value; + updateShowWeekNumbers(); + refill(); + } + + ngModel.$render = function() { + refill( true ); + }; + + scope.select = function( date ) { + if ( mode === 0 ) { + var dt = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0); + dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() ); + ngModel.$setViewValue( dt ); + refill( true ); + } else { + selected = date; + setMode( mode - 1 ); + } + }; + scope.move = function(direction) { + var step = datepickerCtrl.modes[mode].step; + selected.setMonth( selected.getMonth() + direction * (step.months || 0) ); + selected.setFullYear( selected.getFullYear() + direction * (step.years || 0) ); + refill(); + }; + scope.toggleMode = function() { + setMode( (mode + 1) % datepickerCtrl.modes.length ); + }; + scope.getWeekNumber = function(row) { + return ( mode === 0 && scope.showWeekNumbers && row.length === 7 ) ? getISO8601WeekNumber(row[0].date) : null; + }; + + function getISO8601WeekNumber(date) { + var checkDate = new Date(date); + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + } + } + }; +}]) + +.constant('datepickerPopupConfig', { + dateFormat: 'yyyy-MM-dd', + currentText: 'Today', + toggleWeeksText: 'Weeks', + clearText: 'Clear', + closeText: 'Done', + closeOnDateSelection: true, + appendToBody: false, + showButtonBar: true +}) + +.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'datepickerPopupConfig', 'datepickerConfig', +function ($compile, $parse, $document, $position, dateFilter, datepickerPopupConfig, datepickerConfig) { + return { + restrict: 'EA', + require: 'ngModel', + link: function(originalScope, element, attrs, ngModel) { + var scope = originalScope.$new(), // create a child scope so we are not polluting original one + dateFormat, + closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? originalScope.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, + appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? originalScope.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody; + + attrs.$observe('datepickerPopup', function(value) { + dateFormat = value || datepickerPopupConfig.dateFormat; + ngModel.$render(); + }); + + scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? originalScope.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; + + originalScope.$on('$destroy', function() { + $popup.remove(); + scope.$destroy(); + }); + + attrs.$observe('currentText', function(text) { + scope.currentText = angular.isDefined(text) ? text : datepickerPopupConfig.currentText; + }); + attrs.$observe('toggleWeeksText', function(text) { + scope.toggleWeeksText = angular.isDefined(text) ? text : datepickerPopupConfig.toggleWeeksText; + }); + attrs.$observe('clearText', function(text) { + scope.clearText = angular.isDefined(text) ? text : datepickerPopupConfig.clearText; + }); + attrs.$observe('closeText', function(text) { + scope.closeText = angular.isDefined(text) ? text : datepickerPopupConfig.closeText; + }); + + var getIsOpen, setIsOpen; + if ( attrs.isOpen ) { + getIsOpen = $parse(attrs.isOpen); + setIsOpen = getIsOpen.assign; + + originalScope.$watch(getIsOpen, function updateOpen(value) { + scope.isOpen = !! value; + }); + } + scope.isOpen = getIsOpen ? getIsOpen(originalScope) : false; // Initial state + + function setOpen( value ) { + if (setIsOpen) { + setIsOpen(originalScope, !!value); + } else { + scope.isOpen = !!value; + } + } + + var documentClickBind = function(event) { + if (scope.isOpen && event.target !== element[0]) { + scope.$apply(function() { + setOpen(false); + }); + } + }; + + var elementFocusBind = function() { + scope.$apply(function() { + setOpen( true ); + }); + }; + + // popup element used to display calendar + var popupEl = angular.element('
'); + popupEl.attr({ + 'ng-model': 'date', + 'ng-change': 'dateSelection()' + }); + var datepickerEl = angular.element(popupEl.children()[0]), + datepickerOptions = {}; + if (attrs.datepickerOptions) { + datepickerOptions = originalScope.$eval(attrs.datepickerOptions); + datepickerEl.attr(angular.extend({}, datepickerOptions)); + } + + // TODO: reverse from dateFilter string to Date object + function parseDate(viewValue) { + if (!viewValue) { + ngModel.$setValidity('date', true); + return null; + } else if (angular.isDate(viewValue)) { + ngModel.$setValidity('date', true); + return viewValue; + } else if (angular.isString(viewValue)) { + var date = new Date(viewValue); + if (isNaN(date)) { + ngModel.$setValidity('date', false); + return undefined; + } else { + ngModel.$setValidity('date', true); + return date; + } + } else { + ngModel.$setValidity('date', false); + return undefined; + } + } + ngModel.$parsers.unshift(parseDate); + + // Inner change + scope.dateSelection = function(dt) { + if (angular.isDefined(dt)) { + scope.date = dt; + } + ngModel.$setViewValue(scope.date); + ngModel.$render(); + + if (closeOnDateSelection) { + setOpen( false ); + } + }; + + element.bind('input change keyup', function() { + scope.$apply(function() { + scope.date = ngModel.$modelValue; + }); + }); + + // Outter change + ngModel.$render = function() { + var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : ''; + element.val(date); + scope.date = ngModel.$modelValue; + }; + + function addWatchableAttribute(attribute, scopeProperty, datepickerAttribute) { + if (attribute) { + originalScope.$watch($parse(attribute), function(value){ + scope[scopeProperty] = value; + }); + datepickerEl.attr(datepickerAttribute || scopeProperty, scopeProperty); + } + } + addWatchableAttribute(attrs.min, 'min'); + addWatchableAttribute(attrs.max, 'max'); + if (attrs.showWeeks) { + addWatchableAttribute(attrs.showWeeks, 'showWeeks', 'show-weeks'); + } else { + scope.showWeeks = 'show-weeks' in datepickerOptions ? datepickerOptions['show-weeks'] : datepickerConfig.showWeeks; + datepickerEl.attr('show-weeks', 'showWeeks'); + } + if (attrs.dateDisabled) { + datepickerEl.attr('date-disabled', attrs.dateDisabled); + } + + function updatePosition() { + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop('offsetHeight'); + } + + var documentBindingInitialized = false, elementFocusInitialized = false; + scope.$watch('isOpen', function(value) { + if (value) { + updatePosition(); + $document.bind('click', documentClickBind); + if(elementFocusInitialized) { + element.unbind('focus', elementFocusBind); + } + element[0].focus(); + documentBindingInitialized = true; + } else { + if(documentBindingInitialized) { + $document.unbind('click', documentClickBind); + } + element.bind('focus', elementFocusBind); + elementFocusInitialized = true; + } + + if ( setIsOpen ) { + setIsOpen(originalScope, value); + } + }); + + scope.today = function() { + scope.dateSelection(new Date()); + }; + scope.clear = function() { + scope.dateSelection(null); + }; + + var $popup = $compile(popupEl)(scope); + if ( appendToBody ) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + } + }; +}]) + +.directive('datepickerPopupWrap', function() { + return { + restrict:'EA', + replace: true, + transclude: true, + templateUrl: 'template/datepicker/popup.html', + link:function (scope, element, attrs) { + element.bind('click', function(event) { + event.preventDefault(); + event.stopPropagation(); + }); + } + }; +}); + +/* + * dropdownToggle - Provides dropdown menu functionality in place of bootstrap js + * @restrict class or attribute + * @example: + + */ + +angular.module('ui.bootstrap.dropdownToggle', []).directive('dropdownToggle', ['$document', '$location', function ($document, $location) { + var openElement = null, + closeMenu = angular.noop; + return { + restrict: 'CA', + link: function(scope, element, attrs) { + scope.$watch('$location.path', function() { closeMenu(); }); + element.parent().bind('click', function() { closeMenu(); }); + element.bind('click', function (event) { + + var elementWasOpen = (element === openElement); + + event.preventDefault(); + event.stopPropagation(); + + if (!!openElement) { + closeMenu(); + } + + if (!elementWasOpen && !element.hasClass('disabled') && !element.prop('disabled')) { + element.parent().addClass('open'); + openElement = element; + closeMenu = function (event) { + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + $document.unbind('click', closeMenu); + element.parent().removeClass('open'); + closeMenu = angular.noop; + openElement = null; + }; + $document.bind('click', closeMenu); + } + }); + } + }; +}]); + +angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition']) + +/** + * A helper, internal data structure that acts as a map but also allows getting / removing + * elements in the LIFO order + */ + .factory('$$stackedMap', function () { + return { + createNew: function () { + var stack = []; + + return { + add: function (key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function (key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function () { + return stack[stack.length - 1]; + }, + remove: function (key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } + } + return stack.splice(idx, 1)[0]; + }, + removeTop: function () { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function () { + return stack.length; + } + }; + } + }; + }) + +/** + * A helper directive for the $modal service. It creates a backdrop element. + */ + .directive('modalBackdrop', ['$timeout', function ($timeout) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/modal/backdrop.html', + link: function (scope) { + + scope.animate = false; + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + } + }; + }]) + + .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) { + return { + restrict: 'EA', + scope: { + index: '@', + animate: '=' + }, + replace: true, + transclude: true, + templateUrl: 'template/modal/window.html', + link: function (scope, element, attrs) { + scope.windowClass = attrs.windowClass || ''; + + $timeout(function () { + // trigger CSS transitions + scope.animate = true; + // focus a freshly-opened modal + element[0].focus(); + }); + + scope.close = function (evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, 'backdrop click'); + } + }; + } + }; + }]) + + .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap', + function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) { + + var OPENED_MODAL_CLASS = 'modal-open'; + + var backdropDomEl, backdropScope; + var openedWindows = $$stackedMap.createNew(); + var $modalStack = {}; + + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; + } + } + return topBackdropIndex; + } + + $rootScope.$watch(backdropIndex, function(newBackdropIndex){ + if (backdropScope) { + backdropScope.index = newBackdropIndex; + } + }); + + function removeModalWindow(modalInstance) { + + var body = $document.find('body').eq(0); + var modalWindow = openedWindows.get(modalInstance).value; + + //clean up the stack + openedWindows.remove(modalInstance); + + //remove window DOM element + removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, checkRemoveBackdrop); + body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0); + } + + function checkRemoveBackdrop() { + //remove backdrop if no longer needed + if (backdropDomEl && backdropIndex() == -1) { + var backdropScopeRef = backdropScope; + removeAfterAnimate(backdropDomEl, backdropScope, 150, function () { + backdropScopeRef.$destroy(); + backdropScopeRef = null; + }); + backdropDomEl = undefined; + backdropScope = undefined; + } + } + + function removeAfterAnimate(domEl, scope, emulateTime, done) { + // Closing animation + scope.animate = false; + + var transitionEndEventName = $transition.transitionEndEventName; + if (transitionEndEventName) { + // transition out + var timeout = $timeout(afterAnimating, emulateTime); + + domEl.bind(transitionEndEventName, function () { + $timeout.cancel(timeout); + afterAnimating(); + scope.$apply(); + }); + } else { + // Ensure this call is async + $timeout(afterAnimating, 0); + } + + function afterAnimating() { + if (afterAnimating.done) { + return; + } + afterAnimating.done = true; + + domEl.remove(); + if (done) { + done(); + } + } + } + + $document.bind('keydown', function (evt) { + var modal; + + if (evt.which === 27) { + modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + $rootScope.$apply(function () { + $modalStack.dismiss(modal.key); + }); + } + } + }); + + $modalStack.open = function (modalInstance, modal) { + + openedWindows.add(modalInstance, { + deferred: modal.deferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard + }); + + var body = $document.find('body').eq(0), + currBackdropIndex = backdropIndex(); + + if (currBackdropIndex >= 0 && !backdropDomEl) { + backdropScope = $rootScope.$new(true); + backdropScope.index = currBackdropIndex; + backdropDomEl = $compile('
')(backdropScope); + body.append(backdropDomEl); + } + + var angularDomEl = angular.element('
'); + angularDomEl.attr('window-class', modal.windowClass); + angularDomEl.attr('index', openedWindows.length() - 1); + angularDomEl.attr('animate', 'animate'); + angularDomEl.html(modal.content); + + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + body.append(modalDomEl); + body.addClass(OPENED_MODAL_CLASS); + }; + + $modalStack.close = function (modalInstance, result) { + var modalWindow = openedWindows.get(modalInstance).value; + if (modalWindow) { + modalWindow.deferred.resolve(result); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismiss = function (modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance).value; + if (modalWindow) { + modalWindow.deferred.reject(reason); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismissAll = function (reason) { + var topModal = this.getTop(); + while (topModal) { + this.dismiss(topModal.key, reason); + topModal = this.getTop(); + } + }; + + $modalStack.getTop = function () { + return openedWindows.top(); + }; + + return $modalStack; + }]) + + .provider('$modal', function () { + + var $modalProvider = { + options: { + backdrop: true, //can be also false or 'static' + keyboard: true + }, + $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack', + function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) { + + var $modal = {}; + + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : + $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) { + return result.data; + }); + } + + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function (value, key) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } + }); + return promisesArr; + } + + $modal.open = function (modalOptions) { + + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + + //prepare an instance of a modal to be injected into controllers and returned to a caller + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + close: function (result) { + $modalStack.close(modalInstance, result); + }, + dismiss: function (reason) { + $modalStack.dismiss(modalInstance, reason); + } + }; + + //merge and clean up options + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + + //verify options + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error('One of template or templateUrl options is required.'); + } + + var templateAndResolvePromise = + $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve))); + + + templateAndResolvePromise.then(function resolveSuccess(tplAndVars) { + + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + + //controllers + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function (value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + } + + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + content: tplAndVars[0], + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + windowClass: modalOptions.windowClass + }); + + }, function resolveError(reason) { + modalResultDeferred.reject(reason); + }); + + templateAndResolvePromise.then(function () { + modalOpenedDeferred.resolve(true); + }, function () { + modalOpenedDeferred.reject(false); + }); + + return modalInstance; + }; + + return $modal; + }] + }; + + return $modalProvider; + }); + +angular.module('ui.bootstrap.pagination', []) + +.controller('PaginationController', ['$scope', '$attrs', '$parse', '$interpolate', function ($scope, $attrs, $parse, $interpolate) { + var self = this, + setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; + + this.init = function(defaultItemsPerPage) { + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = defaultItemsPerPage; + } + }; + + this.noPrevious = function() { + return this.page === 1; + }; + this.noNext = function() { + return this.page === $scope.totalPages; + }; + + this.isActive = function(page) { + return this.page === page; + }; + + this.calculateTotalPages = function() { + var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + return Math.max(totalPages || 0, 1); + }; + + this.getAttributeValue = function(attribute, defaultValue, interpolate) { + return angular.isDefined(attribute) ? (interpolate ? $interpolate(attribute)($scope.$parent) : $scope.$parent.$eval(attribute)) : defaultValue; + }; + + this.render = function() { + this.page = parseInt($scope.page, 10) || 1; + if (this.page > 0 && this.page <= $scope.totalPages) { + $scope.pages = this.getPages(this.page, $scope.totalPages); + } + }; + + $scope.selectPage = function(page) { + if ( ! self.isActive(page) && page > 0 && page <= $scope.totalPages) { + $scope.page = page; + $scope.onSelectPage({ page: page }); + } + }; + + $scope.$watch('page', function() { + self.render(); + }); + + $scope.$watch('totalItems', function() { + $scope.totalPages = self.calculateTotalPages(); + }); + + $scope.$watch('totalPages', function(value) { + setNumPages($scope.$parent, value); // Readonly variable + + if ( self.page > value ) { + $scope.selectPage(value); + } else { + self.render(); + } + }); +}]) + +.constant('paginationConfig', { + itemsPerPage: 10, + boundaryLinks: false, + directionLinks: true, + firstText: 'First', + previousText: 'Previous', + nextText: 'Next', + lastText: 'Last', + rotate: true +}) + +.directive('pagination', ['$parse', 'paginationConfig', function($parse, config) { + return { + restrict: 'EA', + scope: { + page: '=', + totalItems: '=', + onSelectPage:' &' + }, + controller: 'PaginationController', + templateUrl: 'template/pagination/pagination.html', + replace: true, + link: function(scope, element, attrs, paginationCtrl) { + + // Setup configuration parameters + var maxSize, + boundaryLinks = paginationCtrl.getAttributeValue(attrs.boundaryLinks, config.boundaryLinks ), + directionLinks = paginationCtrl.getAttributeValue(attrs.directionLinks, config.directionLinks ), + firstText = paginationCtrl.getAttributeValue(attrs.firstText, config.firstText, true), + previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), + nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), + lastText = paginationCtrl.getAttributeValue(attrs.lastText, config.lastText, true), + rotate = paginationCtrl.getAttributeValue(attrs.rotate, config.rotate); + + paginationCtrl.init(config.itemsPerPage); + + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); + } + + // Create page object used in template + function makePage(number, text, isActive, isDisabled) { + return { + number: number, + text: text, + active: isActive, + disabled: isDisabled + }; + } + + paginationCtrl.getPages = function(currentPage, totalPages) { + var pages = []; + + // Default page limits + var startPage = 1, endPage = totalPages; + var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); + + // recompute if maxSize + if ( isMaxSized ) { + if ( rotate ) { + // Current page is displayed in the middle of the visible ones + startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); + endPage = startPage + maxSize - 1; + + // Adjust if limit is exceeded + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; + } + } else { + // Visible pages are paginated with maxSize + startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; + + // Adjust last page if limit is exceeded + endPage = Math.min(startPage + maxSize - 1, totalPages); + } + } + + // Add page number links + for (var number = startPage; number <= endPage; number++) { + var page = makePage(number, number, paginationCtrl.isActive(number), false); + pages.push(page); + } + + // Add links to move between page sets + if ( isMaxSized && ! rotate ) { + if ( startPage > 1 ) { + var previousPageSet = makePage(startPage - 1, '...', false, false); + pages.unshift(previousPageSet); + } + + if ( endPage < totalPages ) { + var nextPageSet = makePage(endPage + 1, '...', false, false); + pages.push(nextPageSet); + } + } + + // Add previous & next links + if (directionLinks) { + var previousPage = makePage(currentPage - 1, previousText, false, paginationCtrl.noPrevious()); + pages.unshift(previousPage); + + var nextPage = makePage(currentPage + 1, nextText, false, paginationCtrl.noNext()); + pages.push(nextPage); + } + + // Add first & last links + if (boundaryLinks) { + var firstPage = makePage(1, firstText, false, paginationCtrl.noPrevious()); + pages.unshift(firstPage); + + var lastPage = makePage(totalPages, lastText, false, paginationCtrl.noNext()); + pages.push(lastPage); + } + + return pages; + }; + } + }; +}]) + +.constant('pagerConfig', { + itemsPerPage: 10, + previousText: '« Previous', + nextText: 'Next »', + align: true +}) + +.directive('pager', ['pagerConfig', function(config) { + return { + restrict: 'EA', + scope: { + page: '=', + totalItems: '=', + onSelectPage:' &' + }, + controller: 'PaginationController', + templateUrl: 'template/pagination/pager.html', + replace: true, + link: function(scope, element, attrs, paginationCtrl) { + + // Setup configuration parameters + var previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), + nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), + align = paginationCtrl.getAttributeValue(attrs.align, config.align); + + paginationCtrl.init(config.itemsPerPage); + + // Create page object used in template + function makePage(number, text, isDisabled, isPrevious, isNext) { + return { + number: number, + text: text, + disabled: isDisabled, + previous: ( align && isPrevious ), + next: ( align && isNext ) + }; + } + + paginationCtrl.getPages = function(currentPage) { + return [ + makePage(currentPage - 1, previousText, paginationCtrl.noPrevious(), true, false), + makePage(currentPage + 1, nextText, paginationCtrl.noNext(), false, true) + ]; + }; + } + }; +}]); + +/** + * The following features are still outstanding: animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html tooltips, and selector delegation. + */ +angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) + +/** + * The $tooltip service creates tooltip- and popover-like directives as well as + * houses global options for them. + */ +.provider( '$tooltip', function () { + // The default options tooltip and popover. + var defaultOptions = { + placement: 'top', + animation: true, + popupDelay: 0 + }; + + // Default hide triggers for each show trigger + var triggerMap = { + 'mouseenter': 'mouseleave', + 'click': 'click', + 'focus': 'blur' + }; + + // The options specified to the provider globally. + var globalOptions = {}; + + /** + * `options({})` allows global configuration of all tooltips in the + * application. + * + * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) { + * // place tooltips left instead of top by default + * $tooltipProvider.options( { placement: 'left' } ); + * }); + */ + this.options = function( value ) { + angular.extend( globalOptions, value ); + }; + + /** + * This allows you to extend the set of trigger mappings available. E.g.: + * + * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' ); + */ + this.setTriggers = function setTriggers ( triggers ) { + angular.extend( triggerMap, triggers ); + }; + + /** + * This is a helper function for translating camel-case to snake-case. + */ + function snake_case(name){ + var regexp = /[A-Z]/g; + var separator = '-'; + return name.replace(regexp, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); + } + + /** + * Returns the actual instance of the $tooltip service. + * TODO support multiple triggers + */ + this.$get = [ '$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $parse, $document, $position, $interpolate ) { + return function $tooltip ( type, prefix, defaultTriggerShow ) { + var options = angular.extend( {}, defaultOptions, globalOptions ); + + /** + * Returns an object of show and hide triggers. + * + * If a trigger is supplied, + * it is used to show the tooltip; otherwise, it will use the `trigger` + * option passed to the `$tooltipProvider.options` method; else it will + * default to the trigger supplied to this directive factory. + * + * The hide trigger is based on the show trigger. If the `trigger` option + * was passed to the `$tooltipProvider.options` method, it will use the + * mapped trigger from `triggerMap` or the passed trigger if the map is + * undefined; otherwise, it uses the `triggerMap` value of the show + * trigger; else it will just use the show trigger. + */ + function getTriggers ( trigger ) { + var show = trigger || options.trigger || defaultTriggerShow; + var hide = triggerMap[show] || show; + return { + show: show, + hide: hide + }; + } + + var directiveName = snake_case( type ); + + var startSym = $interpolate.startSymbol(); + var endSym = $interpolate.endSymbol(); + var template = + '
'+ + '
'; + + return { + restrict: 'EA', + scope: true, + compile: function (tElem, tAttrs) { + var tooltipLinker = $compile( template ); + + return function link ( scope, element, attrs ) { + var tooltip; + var transitionTimeout; + var popupTimeout; + var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false; + var triggers = getTriggers( undefined ); + var hasRegisteredTriggers = false; + var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']); + + var positionTooltip = function (){ + var position, + ttWidth, + ttHeight, + ttPosition; + // Get the position of the directive element. + position = appendToBody ? $position.offset( element ) : $position.position( element ); + + // Get the height and width of the tooltip so we can center it. + ttWidth = tooltip.prop( 'offsetWidth' ); + ttHeight = tooltip.prop( 'offsetHeight' ); + + // Calculate the tooltip's top and left coordinates to center it with + // this directive. + switch ( scope.tt_placement ) { + case 'right': + ttPosition = { + top: position.top + position.height / 2 - ttHeight / 2, + left: position.left + position.width + }; + break; + case 'bottom': + ttPosition = { + top: position.top + position.height, + left: position.left + position.width / 2 - ttWidth / 2 + }; + break; + case 'left': + ttPosition = { + top: position.top + position.height / 2 - ttHeight / 2, + left: position.left - ttWidth + }; + break; + default: + ttPosition = { + top: position.top - ttHeight, + left: position.left + position.width / 2 - ttWidth / 2 + }; + break; + } + + ttPosition.top += 'px'; + ttPosition.left += 'px'; + + // Now set the calculated positioning. + tooltip.css( ttPosition ); + + }; + + // By default, the tooltip is not open. + // TODO add ability to start tooltip opened + scope.tt_isOpen = false; + + function toggleTooltipBind () { + if ( ! scope.tt_isOpen ) { + showTooltipBind(); + } else { + hideTooltipBind(); + } + } + + // Show the tooltip with delay if specified, otherwise show it immediately + function showTooltipBind() { + if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) { + return; + } + if ( scope.tt_popupDelay ) { + popupTimeout = $timeout( show, scope.tt_popupDelay, false ); + popupTimeout.then(function(reposition){reposition();}); + } else { + show()(); + } + } + + function hideTooltipBind () { + scope.$apply(function () { + hide(); + }); + } + + // Show the tooltip popup element. + function show() { + + + // Don't show empty tooltips. + if ( ! scope.tt_content ) { + return angular.noop; + } + + createTooltip(); + + // If there is a pending remove transition, we must cancel it, lest the + // tooltip be mysteriously removed. + if ( transitionTimeout ) { + $timeout.cancel( transitionTimeout ); + } + + // Set the initial positioning. + tooltip.css({ top: 0, left: 0, display: 'block' }); + + // Now we add it to the DOM because need some info about it. But it's not + // visible yet anyway. + if ( appendToBody ) { + $document.find( 'body' ).append( tooltip ); + } else { + element.after( tooltip ); + } + + positionTooltip(); + + // And show the tooltip. + scope.tt_isOpen = true; + scope.$digest(); // digest required as $apply is not called + + // Return positioning function as promise callback for correct + // positioning after draw. + return positionTooltip; + } + + // Hide the tooltip popup element. + function hide() { + // First things first: we don't show it anymore. + scope.tt_isOpen = false; + + //if tooltip is going to be shown after delay, we must cancel this + $timeout.cancel( popupTimeout ); + + // And now we remove it from the DOM. However, if we have animation, we + // need to wait for it to expire beforehand. + // FIXME: this is a placeholder for a port of the transitions library. + if ( scope.tt_animation ) { + transitionTimeout = $timeout(removeTooltip, 500); + } else { + removeTooltip(); + } + } + + function createTooltip() { + // There can only be one tooltip element per directive shown at once. + if (tooltip) { + removeTooltip(); + } + tooltip = tooltipLinker(scope, function () {}); + + // Get contents rendered into the tooltip + scope.$digest(); + } + + function removeTooltip() { + if (tooltip) { + tooltip.remove(); + tooltip = null; + } + } + + /** + * Observe the relevant attributes. + */ + attrs.$observe( type, function ( val ) { + scope.tt_content = val; + + if (!val && scope.tt_isOpen ) { + hide(); + } + }); + + attrs.$observe( prefix+'Title', function ( val ) { + scope.tt_title = val; + }); + + attrs.$observe( prefix+'Placement', function ( val ) { + scope.tt_placement = angular.isDefined( val ) ? val : options.placement; + }); + + attrs.$observe( prefix+'PopupDelay', function ( val ) { + var delay = parseInt( val, 10 ); + scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay; + }); + + var unregisterTriggers = function() { + if (hasRegisteredTriggers) { + element.unbind( triggers.show, showTooltipBind ); + element.unbind( triggers.hide, hideTooltipBind ); + } + }; + + attrs.$observe( prefix+'Trigger', function ( val ) { + unregisterTriggers(); + + triggers = getTriggers( val ); + + if ( triggers.show === triggers.hide ) { + element.bind( triggers.show, toggleTooltipBind ); + } else { + element.bind( triggers.show, showTooltipBind ); + element.bind( triggers.hide, hideTooltipBind ); + } + + hasRegisteredTriggers = true; + }); + + var animation = scope.$eval(attrs[prefix + 'Animation']); + scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation; + + attrs.$observe( prefix+'AppendToBody', function ( val ) { + appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : appendToBody; + }); + + // if a tooltip is attached to we need to remove it on + // location change as its parent scope will probably not be destroyed + // by the change. + if ( appendToBody ) { + scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () { + if ( scope.tt_isOpen ) { + hide(); + } + }); + } + + // Make sure tooltip is destroyed and removed. + scope.$on('$destroy', function onDestroyTooltip() { + $timeout.cancel( transitionTimeout ); + $timeout.cancel( popupTimeout ); + unregisterTriggers(); + removeTooltip(); + }); + }; + } + }; + }; + }]; +}) + +.directive( 'tooltipPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-popup.html' + }; +}) + +.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltip', 'tooltip', 'mouseenter' ); +}]) + +.directive( 'tooltipHtmlUnsafePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html' + }; +}) + +.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' ); +}]); + +/** + * The following features are still outstanding: popup delay, animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html popovers, and selector delegatation. + */ +angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] ) + +.directive( 'popoverPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/popover/popover.html' + }; +}) + +.directive( 'popover', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'popover', 'popover', 'click' ); +}]); + +angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition']) + +.constant('progressConfig', { + animate: true, + max: 100 +}) + +.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', '$transition', function($scope, $attrs, progressConfig, $transition) { + var self = this, + bars = [], + max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max, + animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; + + this.addBar = function(bar, element) { + var oldValue = 0, index = bar.$parent.$index; + if ( angular.isDefined(index) && bars[index] ) { + oldValue = bars[index].value; + } + bars.push(bar); + + this.update(element, bar.value, oldValue); + + bar.$watch('value', function(value, oldValue) { + if (value !== oldValue) { + self.update(element, value, oldValue); + } + }); + + bar.$on('$destroy', function() { + self.removeBar(bar); + }); + }; + + // Update bar element width + this.update = function(element, newValue, oldValue) { + var percent = this.getPercentage(newValue); + + if (animate) { + element.css('width', this.getPercentage(oldValue) + '%'); + $transition(element, {width: percent + '%'}); + } else { + element.css({'transition': 'none', 'width': percent + '%'}); + } + }; + + this.removeBar = function(bar) { + bars.splice(bars.indexOf(bar), 1); + }; + + this.getPercentage = function(value) { + return Math.round(100 * value / max); + }; +}]) + +.directive('progress', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + require: 'progress', + scope: {}, + template: '
' + //templateUrl: 'template/progressbar/progress.html' // Works in AngularJS 1.2 + }; +}) + +.directive('bar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + require: '^progress', + scope: { + value: '=', + type: '@' + }, + templateUrl: 'template/progressbar/bar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, element); + } + }; +}) + +.directive('progressbar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + scope: { + value: '=', + type: '@' + }, + templateUrl: 'template/progressbar/progressbar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, angular.element(element.children()[0])); + } + }; +}); +angular.module('ui.bootstrap.rating', []) + +.constant('ratingConfig', { + max: 5, + stateOn: null, + stateOff: null +}) + +.controller('RatingController', ['$scope', '$attrs', '$parse', 'ratingConfig', function($scope, $attrs, $parse, ratingConfig) { + + this.maxRange = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max; + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; + + this.createRateObjects = function(states) { + var defaultOptions = { + stateOn: this.stateOn, + stateOff: this.stateOff + }; + + for (var i = 0, n = states.length; i < n; i++) { + states[i] = angular.extend({ index: i }, defaultOptions, states[i]); + } + return states; + }; + + // Get objects used in template + $scope.range = angular.isDefined($attrs.ratingStates) ? this.createRateObjects(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createRateObjects(new Array(this.maxRange)); + + $scope.rate = function(value) { + if ( $scope.value !== value && !$scope.readonly ) { + $scope.value = value; + } + }; + + $scope.enter = function(value) { + if ( ! $scope.readonly ) { + $scope.val = value; + } + $scope.onHover({value: value}); + }; + + $scope.reset = function() { + $scope.val = angular.copy($scope.value); + $scope.onLeave(); + }; + + $scope.$watch('value', function(value) { + $scope.val = value; + }); + + $scope.readonly = false; + if ($attrs.readonly) { + $scope.$parent.$watch($parse($attrs.readonly), function(value) { + $scope.readonly = !!value; + }); + } +}]) + +.directive('rating', function() { + return { + restrict: 'EA', + scope: { + value: '=', + onHover: '&', + onLeave: '&' + }, + controller: 'RatingController', + templateUrl: 'template/rating/rating.html', + replace: true + }; +}); + +/** + * @ngdoc overview + * @name ui.bootstrap.tabs + * + * @description + * AngularJS version of the tabs directive. + */ + +angular.module('ui.bootstrap.tabs', []) + +.controller('TabsetController', ['$scope', function TabsetCtrl($scope) { + var ctrl = this, + tabs = ctrl.tabs = $scope.tabs = []; + + ctrl.select = function(tab) { + angular.forEach(tabs, function(tab) { + tab.active = false; + }); + tab.active = true; + }; + + ctrl.addTab = function addTab(tab) { + tabs.push(tab); + if (tabs.length === 1 || tab.active) { + ctrl.select(tab); + } + }; + + ctrl.removeTab = function removeTab(tab) { + var index = tabs.indexOf(tab); + //Select a new tab if the tab to be removed is selected + if (tab.active && tabs.length > 1) { + //If this is the last tab, select the previous tab. else, the next tab. + var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; + ctrl.select(tabs[newActiveIndex]); + } + tabs.splice(index, 1); + }; +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabset + * @restrict EA + * + * @description + * Tabset is the outer container for the tabs directive + * + * @param {boolean=} vertical Whether or not to use vertical styling for the tabs. + * @param {boolean=} justified Whether or not to use justified styling for the tabs. + * + * @example + + + + First Content! + Second Content! + +
+ + First Vertical Content! + Second Vertical Content! + + + First Justified Content! + Second Justified Content! + +
+
+ */ +.directive('tabset', function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + scope: {}, + controller: 'TabsetController', + templateUrl: 'template/tabs/tabset.html', + link: function(scope, element, attrs) { + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; + scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; + scope.type = angular.isDefined(attrs.type) ? scope.$parent.$eval(attrs.type) : 'tabs'; + } + }; +}) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tab + * @restrict EA + * + * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}. + * @param {string=} select An expression to evaluate when the tab is selected. + * @param {boolean=} active A binding, telling whether or not this tab is selected. + * @param {boolean=} disabled A binding, telling whether or not this tab is disabled. + * + * @description + * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}. + * + * @example + + +
+ + +
+ + First Tab + + Alert me! + Second Tab, with alert callback and html heading! + + + {{item.content}} + + +
+
+ + function TabsDemoCtrl($scope) { + $scope.items = [ + { title:"Dynamic Title 1", content:"Dynamic Item 0" }, + { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true } + ]; + + $scope.alertMe = function() { + setTimeout(function() { + alert("You've selected the alert tab!"); + }); + }; + }; + +
+ */ + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabHeading + * @restrict EA + * + * @description + * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element. + * + * @example + + + + + HTML in my titles?! + And some content, too! + + + Icon heading?!? + That's right. + + + + + */ +.directive('tab', ['$parse', function($parse) { + return { + require: '^tabset', + restrict: 'EA', + replace: true, + templateUrl: 'template/tabs/tab.html', + transclude: true, + scope: { + heading: '@', + onSelect: '&select', //This callback is called in contentHeadingTransclude + //once it inserts the tab's content into the dom + onDeselect: '&deselect' + }, + controller: function() { + //Empty controller so other directives can require being 'under' a tab + }, + compile: function(elm, attrs, transclude) { + return function postLink(scope, elm, attrs, tabsetCtrl) { + var getActive, setActive; + if (attrs.active) { + getActive = $parse(attrs.active); + setActive = getActive.assign; + scope.$parent.$watch(getActive, function updateActive(value, oldVal) { + // Avoid re-initializing scope.active as it is already initialized + // below. (watcher is called async during init with value === + // oldVal) + if (value !== oldVal) { + scope.active = !!value; + } + }); + scope.active = getActive(scope.$parent); + } else { + setActive = getActive = angular.noop; + } + + scope.$watch('active', function(active) { + // Note this watcher also initializes and assigns scope.active to the + // attrs.active expression. + setActive(scope.$parent, active); + if (active) { + tabsetCtrl.select(scope); + scope.onSelect(); + } else { + scope.onDeselect(); + } + }); + + scope.disabled = false; + if ( attrs.disabled ) { + scope.$parent.$watch($parse(attrs.disabled), function(value) { + scope.disabled = !! value; + }); + } + + scope.select = function() { + if ( ! scope.disabled ) { + scope.active = true; + } + }; + + tabsetCtrl.addTab(scope); + scope.$on('$destroy', function() { + tabsetCtrl.removeTab(scope); + }); + + + //We need to transclude later, once the content container is ready. + //when this link happens, we're inside a tab heading. + scope.$transcludeFn = transclude; + }; + } + }; +}]) + +.directive('tabHeadingTransclude', [function() { + return { + restrict: 'A', + require: '^tab', + link: function(scope, elm, attrs, tabCtrl) { + scope.$watch('headingElement', function updateHeadingElement(heading) { + if (heading) { + elm.html(''); + elm.append(heading); + } + }); + } + }; +}]) + +.directive('tabContentTransclude', function() { + return { + restrict: 'A', + require: '^tabset', + link: function(scope, elm, attrs) { + var tab = scope.$eval(attrs.tabContentTransclude); + + //Now our tab is ready to be transcluded: both the tab heading area + //and the tab content area are loaded. Transclude 'em both. + tab.$transcludeFn(tab.$parent, function(contents) { + angular.forEach(contents, function(node) { + if (isTabHeading(node)) { + //Let tabHeadingTransclude know. + tab.headingElement = node; + } else { + elm.append(node); + } + }); + }); + } + }; + function isTabHeading(node) { + return node.tagName && ( + node.hasAttribute('tab-heading') || + node.hasAttribute('data-tab-heading') || + node.tagName.toLowerCase() === 'tab-heading' || + node.tagName.toLowerCase() === 'data-tab-heading' + ); + } +}) + +; + +angular.module('ui.bootstrap.timepicker', []) + +.constant('timepickerConfig', { + hourStep: 1, + minuteStep: 1, + showMeridian: true, + meridians: null, + readonlyInput: false, + mousewheel: true +}) + +.directive('timepicker', ['$parse', '$log', 'timepickerConfig', '$locale', function ($parse, $log, timepickerConfig, $locale) { + return { + restrict: 'EA', + require:'?^ngModel', + replace: true, + scope: {}, + templateUrl: 'template/timepicker/timepicker.html', + link: function(scope, element, attrs, ngModel) { + if ( !ngModel ) { + return; // do nothing if no ng-model + } + + var selected = new Date(), + meridians = angular.isDefined(attrs.meridians) ? scope.$parent.$eval(attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; + + var hourStep = timepickerConfig.hourStep; + if (attrs.hourStep) { + scope.$parent.$watch($parse(attrs.hourStep), function(value) { + hourStep = parseInt(value, 10); + }); + } + + var minuteStep = timepickerConfig.minuteStep; + if (attrs.minuteStep) { + scope.$parent.$watch($parse(attrs.minuteStep), function(value) { + minuteStep = parseInt(value, 10); + }); + } + + // 12H / 24H mode + scope.showMeridian = timepickerConfig.showMeridian; + if (attrs.showMeridian) { + scope.$parent.$watch($parse(attrs.showMeridian), function(value) { + scope.showMeridian = !!value; + + if ( ngModel.$error.time ) { + // Evaluate from template + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined( hours ) && angular.isDefined( minutes )) { + selected.setHours( hours ); + refresh(); + } + } else { + updateTemplate(); + } + }); + } + + // Get scope.hours in 24H mode if valid + function getHoursFromTemplate ( ) { + var hours = parseInt( scope.hours, 10 ); + var valid = ( scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24); + if ( !valid ) { + return undefined; + } + + if ( scope.showMeridian ) { + if ( hours === 12 ) { + hours = 0; + } + if ( scope.meridian === meridians[1] ) { + hours = hours + 12; + } + } + return hours; + } + + function getMinutesFromTemplate() { + var minutes = parseInt(scope.minutes, 10); + return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined; + } + + function pad( value ) { + return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value; + } + + // Input elements + var inputs = element.find('input'), hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); + + // Respond on mousewheel spin + var mousewheel = (angular.isDefined(attrs.mousewheel)) ? scope.$eval(attrs.mousewheel) : timepickerConfig.mousewheel; + if ( mousewheel ) { + + var isScrollingUp = function(e) { + if (e.originalEvent) { + e = e.originalEvent; + } + //pick correct delta variable depending on event + var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY; + return (e.detail || delta > 0); + }; + + hoursInputEl.bind('mousewheel wheel', function(e) { + scope.$apply( (isScrollingUp(e)) ? scope.incrementHours() : scope.decrementHours() ); + e.preventDefault(); + }); + + minutesInputEl.bind('mousewheel wheel', function(e) { + scope.$apply( (isScrollingUp(e)) ? scope.incrementMinutes() : scope.decrementMinutes() ); + e.preventDefault(); + }); + } + + scope.readonlyInput = (angular.isDefined(attrs.readonlyInput)) ? scope.$eval(attrs.readonlyInput) : timepickerConfig.readonlyInput; + if ( ! scope.readonlyInput ) { + + var invalidate = function(invalidHours, invalidMinutes) { + ngModel.$setViewValue( null ); + ngModel.$setValidity('time', false); + if (angular.isDefined(invalidHours)) { + scope.invalidHours = invalidHours; + } + if (angular.isDefined(invalidMinutes)) { + scope.invalidMinutes = invalidMinutes; + } + }; + + scope.updateHours = function() { + var hours = getHoursFromTemplate(); + + if ( angular.isDefined(hours) ) { + selected.setHours( hours ); + refresh( 'h' ); + } else { + invalidate(true); + } + }; + + hoursInputEl.bind('blur', function(e) { + if ( !scope.validHours && scope.hours < 10) { + scope.$apply( function() { + scope.hours = pad( scope.hours ); + }); + } + }); + + scope.updateMinutes = function() { + var minutes = getMinutesFromTemplate(); + + if ( angular.isDefined(minutes) ) { + selected.setMinutes( minutes ); + refresh( 'm' ); + } else { + invalidate(undefined, true); + } + }; + + minutesInputEl.bind('blur', function(e) { + if ( !scope.invalidMinutes && scope.minutes < 10 ) { + scope.$apply( function() { + scope.minutes = pad( scope.minutes ); + }); + } + }); + } else { + scope.updateHours = angular.noop; + scope.updateMinutes = angular.noop; + } + + ngModel.$render = function() { + var date = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : null; + + if ( isNaN(date) ) { + ngModel.$setValidity('time', false); + $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else { + if ( date ) { + selected = date; + } + makeValid(); + updateTemplate(); + } + }; + + // Call internally when we know that model is valid. + function refresh( keyboardChange ) { + makeValid(); + ngModel.$setViewValue( new Date(selected) ); + updateTemplate( keyboardChange ); + } + + function makeValid() { + ngModel.$setValidity('time', true); + scope.invalidHours = false; + scope.invalidMinutes = false; + } + + function updateTemplate( keyboardChange ) { + var hours = selected.getHours(), minutes = selected.getMinutes(); + + if ( scope.showMeridian ) { + hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system + } + scope.hours = keyboardChange === 'h' ? hours : pad(hours); + scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes); + scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; + } + + function addMinutes( minutes ) { + var dt = new Date( selected.getTime() + minutes * 60000 ); + selected.setHours( dt.getHours(), dt.getMinutes() ); + refresh(); + } + + scope.incrementHours = function() { + addMinutes( hourStep * 60 ); + }; + scope.decrementHours = function() { + addMinutes( - hourStep * 60 ); + }; + scope.incrementMinutes = function() { + addMinutes( minuteStep ); + }; + scope.decrementMinutes = function() { + addMinutes( - minuteStep ); + }; + scope.toggleMeridian = function() { + addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) ); + }; + } + }; +}]); + +angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml']) + +/** + * A helper service that can parse typeahead's syntax (string provided by users) + * Extracted to a separate service for ease of unit testing + */ + .factory('typeaheadParser', ['$parse', function ($parse) { + + // 00000111000000000000022200000000000000003333333333333330000000000044000 + var TYPEAHEAD_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/; + + return { + parse:function (input) { + + var match = input.match(TYPEAHEAD_REGEXP), modelMapper, viewMapper, source; + if (!match) { + throw new Error( + "Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_'" + + " but got '" + input + "'."); + } + + return { + itemName:match[3], + source:$parse(match[4]), + viewMapper:$parse(match[2] || match[1]), + modelMapper:$parse(match[1]) + }; + } + }; +}]) + + .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', + function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { + + var HOT_KEYS = [9, 13, 27, 38, 40]; + + return { + require:'ngModel', + link:function (originalScope, element, attrs, modelCtrl) { + + //SUPPORTED ATTRIBUTES (OPTIONS) + + //minimal no of characters that needs to be entered before typeahead kicks-in + var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1; + + //minimal wait time after last character typed before typehead kicks-in + var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; + + //should it restrict model values to the ones selected from the popup only? + var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; + + //binding to a variable that indicates if matches are being retrieved asynchronously + var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; + + //a callback executed when a match is selected + var onSelectCallback = $parse(attrs.typeaheadOnSelect); + + var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; + + var appendToBody = attrs.typeaheadAppendToBody ? $parse(attrs.typeaheadAppendToBody) : false; + + //INTERNAL VARIABLES + + //model setter executed upon match selection + var $setModelValue = $parse(attrs.ngModel).assign; + + //expressions used by typeahead + var parserResult = typeaheadParser.parse(attrs.typeahead); + + var hasFocus; + + //pop-up element used to display matches + var popUpEl = angular.element('
'); + popUpEl.attr({ + matches: 'matches', + active: 'activeIdx', + select: 'select(activeIdx)', + query: 'query', + position: 'position' + }); + //custom item template + if (angular.isDefined(attrs.typeaheadTemplateUrl)) { + popUpEl.attr('template-url', attrs.typeaheadTemplateUrl); + } + + //create a child scope for the typeahead directive so we are not polluting original scope + //with typeahead-specific data (matches, query etc.) + var scope = originalScope.$new(); + originalScope.$on('$destroy', function(){ + scope.$destroy(); + }); + + var resetMatches = function() { + scope.matches = []; + scope.activeIdx = -1; + }; + + var getMatchesAsync = function(inputValue) { + + var locals = {$viewValue: inputValue}; + isLoadingSetter(originalScope, true); + $q.when(parserResult.source(originalScope, locals)).then(function(matches) { + + //it might happen that several async queries were in progress if a user were typing fast + //but we are interested only in responses that correspond to the current view value + if (inputValue === modelCtrl.$viewValue && hasFocus) { + if (matches.length > 0) { + + scope.activeIdx = 0; + scope.matches.length = 0; + + //transform labels + for(var i=0; i= minSearch) { + if (waitTime > 0) { + if (timeoutPromise) { + $timeout.cancel(timeoutPromise);//cancel previous timeout + } + timeoutPromise = $timeout(function () { + getMatchesAsync(inputValue); + }, waitTime); + } else { + getMatchesAsync(inputValue); + } + } else { + isLoadingSetter(originalScope, false); + resetMatches(); + } + + if (isEditable) { + return inputValue; + } else { + if (!inputValue) { + // Reset in case user had typed something previously. + modelCtrl.$setValidity('editable', true); + return inputValue; + } else { + modelCtrl.$setValidity('editable', false); + return undefined; + } + } + }); + + modelCtrl.$formatters.push(function (modelValue) { + + var candidateViewValue, emptyViewValue; + var locals = {}; + + if (inputFormatter) { + + locals['$model'] = modelValue; + return inputFormatter(originalScope, locals); + + } else { + + //it might happen that we don't have enough info to properly render input value + //we need to check for this situation and simply return model value if we can't apply custom formatting + locals[parserResult.itemName] = modelValue; + candidateViewValue = parserResult.viewMapper(originalScope, locals); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); + + return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; + } + }); + + scope.select = function (activeIdx) { + //called from within the $digest() cycle + var locals = {}; + var model, item; + + locals[parserResult.itemName] = item = scope.matches[activeIdx].model; + model = parserResult.modelMapper(originalScope, locals); + $setModelValue(originalScope, model); + modelCtrl.$setValidity('editable', true); + + onSelectCallback(originalScope, { + $item: item, + $model: model, + $label: parserResult.viewMapper(originalScope, locals) + }); + + resetMatches(); + + //return focus to the input element if a mach was selected via a mouse click event + element[0].focus(); + }; + + //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27) + element.bind('keydown', function (evt) { + + //typeahead is open and an "interesting" key was pressed + if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { + return; + } + + evt.preventDefault(); + + if (evt.which === 40) { + scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; + scope.$digest(); + + } else if (evt.which === 38) { + scope.activeIdx = (scope.activeIdx ? scope.activeIdx : scope.matches.length) - 1; + scope.$digest(); + + } else if (evt.which === 13 || evt.which === 9) { + scope.$apply(function () { + scope.select(scope.activeIdx); + }); + + } else if (evt.which === 27) { + evt.stopPropagation(); + + resetMatches(); + scope.$digest(); + } + }); + + element.bind('blur', function (evt) { + hasFocus = false; + }); + + // Keep reference to click handler to unbind it. + var dismissClickHandler = function (evt) { + if (element[0] !== evt.target) { + resetMatches(); + scope.$digest(); + } + }; + + $document.bind('click', dismissClickHandler); + + originalScope.$on('$destroy', function(){ + $document.unbind('click', dismissClickHandler); + }); + + var $popup = $compile(popUpEl)(scope); + if ( appendToBody ) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + } + }; + +}]) + + .directive('typeaheadPopup', function () { + return { + restrict:'EA', + scope:{ + matches:'=', + query:'=', + active:'=', + position:'=', + select:'&' + }, + replace:true, + templateUrl:'template/typeahead/typeahead-popup.html', + link:function (scope, element, attrs) { + + scope.templateUrl = attrs.templateUrl; + + scope.isOpen = function () { + return scope.matches.length > 0; + }; + + scope.isActive = function (matchIdx) { + return scope.active == matchIdx; + }; + + scope.selectActive = function (matchIdx) { + scope.active = matchIdx; + }; + + scope.selectMatch = function (activeIdx) { + scope.select({activeIdx:activeIdx}); + }; + } + }; + }) + + .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) { + return { + restrict:'EA', + scope:{ + index:'=', + match:'=', + query:'=' + }, + link:function (scope, element, attrs) { + var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html'; + $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){ + element.replaceWith($compile(tplContent.trim())(scope)); + }); + } + }; + }]) + + .filter('typeaheadHighlight', function() { + + function escapeRegexp(queryToEscape) { + return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); + } + + return function(matchItem, query) { + return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; + }; + }); +angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion-group.html", + "
\n" + + "
\n" + + "

\n" + + " {{heading}}\n" + + "

\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
"); +}]); + +angular.module("template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion.html", + "
"); +}]); + +angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/alert/alert.html", + "
\n" + + " \n" + + "
\n" + + "
\n" + + ""); +}]); + +angular.module("template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/carousel/carousel.html", + "
\n" + + "
    1\">\n" + + "
  1. \n" + + "
\n" + + "
\n" + + " 1\">\n" + + " 1\">\n" + + "
\n" + + ""); +}]); + +angular.module("template/carousel/slide.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/carousel/slide.html", + "
\n" + + ""); +}]); + +angular.module("template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/datepicker.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " 0\" class=\"h6\">\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
#{{label}}
{{ getWeekNumber(row) }}\n" + + " \n" + + "
\n" + + ""); +}]); + +angular.module("template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/popup.html", + "
    \n" + + "
  • \n" + + "
  • \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
  • \n" + + "
\n" + + ""); +}]); + +angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/modal/backdrop.html", + "
"); +}]); + +angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/modal/window.html", + "
\n" + + "
\n" + + "
"); +}]); + +angular.module("template/pagination/pager.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pager.html", + ""); +}]); + +angular.module("template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pagination.html", + ""); +}]); + +angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", + "
\n" + + "
\n" + + "
\n" + + "
\n" + + ""); +}]); + +angular.module("template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-popup.html", + "
\n" + + "
\n" + + "
\n" + + "
\n" + + ""); +}]); + +angular.module("template/popover/popover.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover.html", + "
\n" + + "
\n" + + "\n" + + "
\n" + + "

\n" + + "
\n" + + "
\n" + + "
\n" + + ""); +}]); + +angular.module("template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/bar.html", + "
"); +}]); + +angular.module("template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progress.html", + "
"); +}]); + +angular.module("template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progressbar.html", + "
"); +}]); + +angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/rating/rating.html", + "\n" + + " \n" + + ""); +}]); + +angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tab.html", + "
  • \n" + + " {{heading}}\n" + + "
  • \n" + + ""); +}]); + +angular.module("template/tabs/tabset-titles.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tabset-titles.html", + "
      \n" + + "
    \n" + + ""); +}]); + +angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tabset.html", + "\n" + + "
    \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + ""); +}]); + +angular.module("template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/timepicker/timepicker.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
       
      \n" + + " \n" + + " :\n" + + " \n" + + "
       
      \n" + + ""); +}]); + +angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-match.html", + ""); +}]); + +angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-popup.html", + "
        \n" + + "
      • \n" + + "
        \n" + + "
      • \n" + + "
      "); +}]); diff --git a/dist/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js b/dist/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js new file mode 100644 index 000000000..0830f35b0 --- /dev/null +++ b/dist/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js @@ -0,0 +1,9 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.10.0 - 2014-01-13 + * License: MIT + */ +angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/popup.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0)}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){if(k)k=!1,i(),c.css({height:0});else{c.css({height:c[0].scrollHeight+"px"});{c[0].offsetWidth}c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i)}}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(this.groups.indexOf(a),1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",["$parse",function(a){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(b,c,d,e){var f,g;e.addGroup(b),b.isOpen=!1,d.isOpen&&(f=a(d.isOpen),g=f.assign,b.$parent.$watch(f,function(a){b.isOpen=!!a})),b.$watch("isOpen",function(a){a&&e.closeOthers(b),g&&g(b.$parent,a)})}}}]).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",compile:function(a,b,c){return function(a,b,d,e){e.setHeading(c(a,function(){}))}}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"=",close:"&"}}}),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){b.hasClass(e.activeClass)||a.$apply(function(){f.$setViewValue(a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$transition","$q",function(a,b,c){function d(){e();var c=+a.interval;!isNaN(c)&&c>=0&&(g=b(f,c))}function e(){g&&(b.cancel(g),g=null)}function f(){h?(a.next(),d()):a.pause()}var g,h,i=this,j=i.slides=[],k=-1;i.currentSlide=null;var l=!1;i.select=function(e,f){function g(){if(!l){if(i.currentSlide&&angular.isString(f)&&!a.noTransition&&e.$element){e.$element.addClass(f);{e.$element[0].offsetWidth}angular.forEach(j,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(e,{direction:f,active:!0,entering:!0}),angular.extend(i.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=c(e.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(e,i.currentSlide)}else h(e,i.currentSlide);i.currentSlide=e,k=m,d()}}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var m=j.indexOf(e);void 0===f&&(f=m>k?"next":"prev"),e&&e!==i.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){l=!0}),i.indexOfSlide=function(a){return j.indexOf(a)},a.next=function(){var b=(k+1)%j.length;return a.$currentTransition?void 0:i.select(j[b],"next")},a.prev=function(){var b=0>k-1?j.length-1:k-1;return a.$currentTransition?void 0:i.select(j[b],"prev")},a.select=function(a){i.select(a)},a.isActive=function(a){return i.currentSlide===a},a.slides=function(){return j},a.$watch("interval",d),a.$on("$destroy",e),a.play=function(){h||(h=!0,d())},a.pause=function(){a.noPause||(h=!1,e())},i.addSlide=function(b,c){b.$element=c,j.push(b),1===j.length||b.active?(i.select(j[j.length-1]),1==j.length&&a.play()):b.active=!1},i.removeSlide=function(a){var b=j.indexOf(a);j.splice(b,1),j.length>0&&a.active?b>=j.length?i.select(j[b-1]):i.select(j[b]):k>b&&k--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",["$parse",function(a){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{},link:function(b,c,d,e){if(d.active){var f=a(d.active),g=f.assign,h=b.active=f(b.$parent);b.$watch(function(){var a=f(b.$parent);return a!==b.active&&(a!==h?h=b.active=a:g(b.$parent,a=h=b.active)),a})}e.addSlide(b,c),b.$on("$destroy",function(){e.removeSlide(b)}),b.$watch("active",function(a){a&&e.select(b)})}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].body.scrollTop||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].body.scrollLeft||a[0].documentElement.scrollLeft)}}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.position"]).constant("datepickerConfig",{dayFormat:"dd",monthFormat:"MMMM",yearFormat:"yyyy",dayHeaderFormat:"EEE",dayTitleFormat:"MMMM yyyy",monthTitleFormat:"yyyy",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","dateFilter","datepickerConfig",function(a,b,c,d){function e(b,c){return angular.isDefined(b)?a.$parent.$eval(b):c}function f(a,b){return new Date(a,b,0).getDate()}function g(a,b){for(var c=new Array(b),d=a,e=0;b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a,b,d,e){return{date:a,label:c(a,b),selected:!!d,secondary:!!e}}var i={day:e(b.dayFormat,d.dayFormat),month:e(b.monthFormat,d.monthFormat),year:e(b.yearFormat,d.yearFormat),dayHeader:e(b.dayHeaderFormat,d.dayHeaderFormat),dayTitle:e(b.dayTitleFormat,d.dayTitleFormat),monthTitle:e(b.monthTitleFormat,d.monthTitleFormat)},j=e(b.startingDay,d.startingDay),k=e(b.yearRange,d.yearRange);this.minDate=d.minDate?new Date(d.minDate):null,this.maxDate=d.maxDate?new Date(d.maxDate):null,this.modes=[{name:"day",getVisibleDates:function(a,b){var d=a.getFullYear(),e=a.getMonth(),k=new Date(d,e,1),l=j-k.getDay(),m=l>0?7-l:-l,n=new Date(k),o=0;m>0&&(n.setDate(-m+1),o+=m),o+=f(d,e+1),o+=(7-o%7)%7;for(var p=g(n,o),q=new Array(7),r=0;o>r;r++){var s=new Date(p[r]);p[r]=h(s,i.day,b&&b.getDate()===s.getDate()&&b.getMonth()===s.getMonth()&&b.getFullYear()===s.getFullYear(),s.getMonth()!==e)}for(var t=0;7>t;t++)q[t]=c(p[t].date,i.dayHeader);return{objects:p,title:c(a,i.dayTitle),labels:q}},compare:function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},split:7,step:{months:1}},{name:"month",getVisibleDates:function(a,b){for(var d=new Array(12),e=a.getFullYear(),f=0;12>f;f++){var g=new Date(e,f,1);d[f]=h(g,i.month,b&&b.getMonth()===f&&b.getFullYear()===e)}return{objects:d,title:c(a,i.monthTitle)}},compare:function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},split:3,step:{years:1}},{name:"year",getVisibleDates:function(a,b){for(var c=new Array(k),d=a.getFullYear(),e=parseInt((d-1)/k,10)*k+1,f=0;k>f;f++){var g=new Date(e+f,0,1);c[f]=h(g,i.year,b&&b.getFullYear()===g.getFullYear())}return{objects:c,title:[c[0].label,c[k-1].label].join(" - ")}},compare:function(a,b){return a.getFullYear()-b.getFullYear()},split:5,step:{years:k}}],this.isDisabled=function(b,c){var d=this.modes[c||0];return this.minDate&&d.compare(b,this.minDate)<0||this.maxDate&&d.compare(b,this.maxDate)>0||a.dateDisabled&&a.dateDisabled({date:b,mode:d.name})}}]).directive("datepicker",["dateFilter","$parse","datepickerConfig","$log",function(a,b,c,d){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,e,f,g){function h(){a.showWeekNumbers=0===o&&q}function i(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c}function j(b){var c=null,e=!0;n.$modelValue&&(c=new Date(n.$modelValue),isNaN(c)?(e=!1,d.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):b&&(p=c)),n.$setValidity("date",e);var f=m.modes[o],g=f.getVisibleDates(p,c);angular.forEach(g.objects,function(a){a.disabled=m.isDisabled(a.date,o)}),n.$setValidity("date-disabled",!c||!m.isDisabled(c)),a.rows=i(g.objects,f.split),a.labels=g.labels||[],a.title=g.title}function k(a){o=a,h(),j()}function l(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var m=g[0],n=g[1];if(n){var o=0,p=new Date,q=c.showWeeks;f.showWeeks?a.$parent.$watch(b(f.showWeeks),function(a){q=!!a,h()}):h(),f.min&&a.$parent.$watch(b(f.min),function(a){m.minDate=a?new Date(a):null,j()}),f.max&&a.$parent.$watch(b(f.max),function(a){m.maxDate=a?new Date(a):null,j()}),n.$render=function(){j(!0)},a.select=function(a){if(0===o){var b=n.$modelValue?new Date(n.$modelValue):new Date(0,0,0,0,0,0,0);b.setFullYear(a.getFullYear(),a.getMonth(),a.getDate()),n.$setViewValue(b),j(!0)}else p=a,k(o-1)},a.move=function(a){var b=m.modes[o].step;p.setMonth(p.getMonth()+a*(b.months||0)),p.setFullYear(p.getFullYear()+a*(b.years||0)),j()},a.toggleMode=function(){k((o+1)%m.modes.length)},a.getWeekNumber=function(b){return 0===o&&a.showWeekNumbers&&7===b.length?l(b[0].date):null}}}}}]).constant("datepickerPopupConfig",{dateFormat:"yyyy-MM-dd",currentText:"Today",toggleWeeksText:"Weeks",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","datepickerPopupConfig","datepickerConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",link:function(h,i,j,k){function l(a){u?u(h,!!a):q.isOpen=!!a}function m(a){if(a){if(angular.isDate(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=new Date(a);return isNaN(b)?(k.$setValidity("date",!1),void 0):(k.$setValidity("date",!0),b)}return k.$setValidity("date",!1),void 0}return k.$setValidity("date",!0),null}function n(a,c,d){a&&(h.$watch(b(a),function(a){q[c]=a}),y.attr(d||c,c))}function o(){q.position=s?d.offset(i):d.position(i),q.position.top=q.position.top+i.prop("offsetHeight")}var p,q=h.$new(),r=angular.isDefined(j.closeOnDateSelection)?h.$eval(j.closeOnDateSelection):f.closeOnDateSelection,s=angular.isDefined(j.datepickerAppendToBody)?h.$eval(j.datepickerAppendToBody):f.appendToBody;j.$observe("datepickerPopup",function(a){p=a||f.dateFormat,k.$render()}),q.showButtonBar=angular.isDefined(j.showButtonBar)?h.$eval(j.showButtonBar):f.showButtonBar,h.$on("$destroy",function(){C.remove(),q.$destroy()}),j.$observe("currentText",function(a){q.currentText=angular.isDefined(a)?a:f.currentText}),j.$observe("toggleWeeksText",function(a){q.toggleWeeksText=angular.isDefined(a)?a:f.toggleWeeksText}),j.$observe("clearText",function(a){q.clearText=angular.isDefined(a)?a:f.clearText}),j.$observe("closeText",function(a){q.closeText=angular.isDefined(a)?a:f.closeText});var t,u;j.isOpen&&(t=b(j.isOpen),u=t.assign,h.$watch(t,function(a){q.isOpen=!!a})),q.isOpen=t?t(h):!1;var v=function(a){q.isOpen&&a.target!==i[0]&&q.$apply(function(){l(!1)})},w=function(){q.$apply(function(){l(!0)})},x=angular.element("
      ");x.attr({"ng-model":"date","ng-change":"dateSelection()"});var y=angular.element(x.children()[0]),z={};j.datepickerOptions&&(z=h.$eval(j.datepickerOptions),y.attr(angular.extend({},z))),k.$parsers.unshift(m),q.dateSelection=function(a){angular.isDefined(a)&&(q.date=a),k.$setViewValue(q.date),k.$render(),r&&l(!1)},i.bind("input change keyup",function(){q.$apply(function(){q.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,p):"";i.val(a),q.date=k.$modelValue},n(j.min,"min"),n(j.max,"max"),j.showWeeks?n(j.showWeeks,"showWeeks","show-weeks"):(q.showWeeks="show-weeks"in z?z["show-weeks"]:g.showWeeks,y.attr("show-weeks","showWeeks")),j.dateDisabled&&y.attr("date-disabled",j.dateDisabled);var A=!1,B=!1;q.$watch("isOpen",function(a){a?(o(),c.bind("click",v),B&&i.unbind("focus",w),i[0].focus(),A=!0):(A&&c.unbind("click",v),i.bind("focus",w),B=!0),u&&u(h,a)}),q.today=function(){q.dateSelection(new Date)},q.clear=function(){q.dateSelection(null)};var C=a(x)(q);s?c.find("body").append(C):i.after(C)}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdownToggle",[]).directive("dropdownToggle",["$document","$location",function(a){var b=null,c=angular.noop;return{restrict:"CA",link:function(d,e){d.$watch("$location.path",function(){c()}),e.parent().bind("click",function(){c()}),e.bind("click",function(d){var f=e===b;d.preventDefault(),d.stopPropagation(),b&&c(),f||e.hasClass("disabled")||e.prop("disabled")||(e.parent().addClass("open"),b=e,c=function(d){d&&(d.preventDefault(),d.stopPropagation()),a.unbind("click",c),e.parent().removeClass("open"),c=angular.noop,b=null},a.bind("click",c))})}}}]),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0)}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g,0)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&e.$apply(function(){o.dismiss(b.key)}))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();h>=0&&!k&&(l=e.$new(!0),l.index=h,k=d("
      ")(l),f.append(k));var i=angular.element("
      ");i.attr("window-class",b.windowClass),i.attr("index",n.length()-1),i.attr("animate","animate"),i.html(b.content);var j=d(i)(b.scope);n.top().value.modalDomEl=j,f.append(j),f.addClass(m)},o.close=function(a,b){var c=n.get(a).value;c&&(c.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a).value;c&&(c.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,windowClass:b.windowClass})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse","$interpolate",function(a,b,c,d){var e=this,f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(d){b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){e.itemsPerPage=parseInt(b,10),a.totalPages=e.calculateTotalPages()}):this.itemsPerPage=d},this.noPrevious=function(){return 1===this.page},this.noNext=function(){return this.page===a.totalPages},this.isActive=function(a){return this.page===a},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.getAttributeValue=function(b,c,e){return angular.isDefined(b)?e?d(b)(a.$parent):a.$parent.$eval(b):c},this.render=function(){this.page=parseInt(a.page,10)||1,this.page>0&&this.page<=a.totalPages&&(a.pages=this.getPages(this.page,a.totalPages))},a.selectPage=function(b){!e.isActive(b)&&b>0&&b<=a.totalPages&&(a.page=b,a.onSelectPage({page:b}))},a.$watch("page",function(){e.render()}),a.$watch("totalItems",function(){a.totalPages=e.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),e.page>b?a.selectPage(b):e.render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{page:"=",totalItems:"=",onSelectPage:" &"},controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c,d){return{number:a,text:b,active:c,disabled:d}}var h,i=f.getAttributeValue(e.boundaryLinks,b.boundaryLinks),j=f.getAttributeValue(e.directionLinks,b.directionLinks),k=f.getAttributeValue(e.firstText,b.firstText,!0),l=f.getAttributeValue(e.previousText,b.previousText,!0),m=f.getAttributeValue(e.nextText,b.nextText,!0),n=f.getAttributeValue(e.lastText,b.lastText,!0),o=f.getAttributeValue(e.rotate,b.rotate);f.init(b.itemsPerPage),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){h=parseInt(a,10),f.render()}),f.getPages=function(a,b){var c=[],d=1,e=b,p=angular.isDefined(h)&&b>h;p&&(o?(d=Math.max(a-Math.floor(h/2),1),e=d+h-1,e>b&&(e=b,d=e-h+1)):(d=(Math.ceil(a/h)-1)*h+1,e=Math.min(d+h-1,b)));for(var q=d;e>=q;q++){var r=g(q,q,f.isActive(q),!1);c.push(r)}if(p&&!o){if(d>1){var s=g(d-1,"...",!1,!1);c.unshift(s)}if(b>e){var t=g(e+1,"...",!1,!1);c.push(t)}}if(j){var u=g(a-1,l,!1,f.noPrevious());c.unshift(u);var v=g(a+1,m,!1,f.noNext());c.push(v)}if(i){var w=g(1,k,!1,f.noPrevious());c.unshift(w);var x=g(b,n,!1,f.noNext());c.push(x)}return c}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{page:"=",totalItems:"=",onSelectPage:" &"},controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){function f(a,b,c,d,e){return{number:a,text:b,disabled:c,previous:i&&d,next:i&&e}}var g=e.getAttributeValue(d.previousText,a.previousText,!0),h=e.getAttributeValue(d.nextText,a.nextText,!0),i=e.getAttributeValue(d.align,a.align);e.init(a.itemsPerPage),e.getPages=function(a){return[f(a-1,g,e.noPrevious(),!0,!1),f(a+1,h,e.noNext(),!1,!0)]}}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$parse","$document","$position","$interpolate",function(e,f,g,h,i,j,k){return function(e,l,m){function n(a){var b=a||o.trigger||m,d=c[b]||b;return{show:b,hide:d}}var o=angular.extend({},b,d),p=a(e),q=k.startSymbol(),r=k.endSymbol(),s="
      ';return{restrict:"EA",scope:!0,compile:function(){var a=f(s);return function(b,c,d){function f(){b.tt_isOpen?m():k()}function k(){(!z||b.$eval(d[l+"Enable"]))&&(b.tt_popupDelay?(v=g(p,b.tt_popupDelay,!1),v.then(function(a){a()})):p()())}function m(){b.$apply(function(){q()})}function p(){return b.tt_content?(r(),u&&g.cancel(u),t.css({top:0,left:0,display:"block"}),w?i.find("body").append(t):c.after(t),A(),b.tt_isOpen=!0,b.$digest(),A):angular.noop}function q(){b.tt_isOpen=!1,g.cancel(v),b.tt_animation?u=g(s,500):s()}function r(){t&&s(),t=a(b,function(){}),b.$digest()}function s(){t&&(t.remove(),t=null)}var t,u,v,w=angular.isDefined(o.appendToBody)?o.appendToBody:!1,x=n(void 0),y=!1,z=angular.isDefined(d[l+"Enable"]),A=function(){var a,d,e,f;switch(a=w?j.offset(c):j.position(c),d=t.prop("offsetWidth"),e=t.prop("offsetHeight"),b.tt_placement){case"right":f={top:a.top+a.height/2-e/2,left:a.left+a.width};break;case"bottom":f={top:a.top+a.height,left:a.left+a.width/2-d/2};break;case"left":f={top:a.top+a.height/2-e/2,left:a.left-d};break;default:f={top:a.top-e,left:a.left+a.width/2-d/2}}f.top+="px",f.left+="px",t.css(f)};b.tt_isOpen=!1,d.$observe(e,function(a){b.tt_content=a,!a&&b.tt_isOpen&&q()}),d.$observe(l+"Title",function(a){b.tt_title=a}),d.$observe(l+"Placement",function(a){b.tt_placement=angular.isDefined(a)?a:o.placement}),d.$observe(l+"PopupDelay",function(a){var c=parseInt(a,10);b.tt_popupDelay=isNaN(c)?o.popupDelay:c});var B=function(){y&&(c.unbind(x.show,k),c.unbind(x.hide,m))};d.$observe(l+"Trigger",function(a){B(),x=n(a),x.show===x.hide?c.bind(x.show,f):(c.bind(x.show,k),c.bind(x.hide,m)),y=!0});var C=b.$eval(d[l+"Animation"]);b.tt_animation=angular.isDefined(C)?!!C:o.animation,d.$observe(l+"AppendToBody",function(a){w=angular.isDefined(a)?h(a)(b):w}),w&&b.$on("$locationChangeSuccess",function(){b.tt_isOpen&&q()}),b.$on("$destroy",function(){g.cancel(u),g.cancel(v),B(),s()})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",["ui.bootstrap.transition"]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig","$transition",function(a,b,c,d){var e=this,f=[],g=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,h=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.addBar=function(a,b){var c=0,d=a.$parent.$index;angular.isDefined(d)&&f[d]&&(c=f[d].value),f.push(a),this.update(b,a.value,c),a.$watch("value",function(a,c){a!==c&&e.update(b,a,c)}),a.$on("$destroy",function(){e.removeBar(a)})},this.update=function(a,b,c){var e=this.getPercentage(b);h?(a.css("width",this.getPercentage(c)+"%"),d(a,{width:e+"%"})):a.css({transition:"none",width:e+"%"})},this.removeBar=function(a){f.splice(f.indexOf(a),1)},this.getPercentage=function(a){return Math.round(100*a/g)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},template:'
      '}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","$parse","ratingConfig",function(a,b,c,d){this.maxRange=angular.isDefined(b.max)?a.$parent.$eval(b.max):d.max,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):d.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):d.stateOff,this.createRateObjects=function(a){for(var b={stateOn:this.stateOn,stateOff:this.stateOff},c=0,d=a.length;d>c;c++)a[c]=angular.extend({index:c},b,a[c]);return a},a.range=angular.isDefined(b.ratingStates)?this.createRateObjects(angular.copy(a.$parent.$eval(b.ratingStates))):this.createRateObjects(new Array(this.maxRange)),a.rate=function(b){a.value===b||a.readonly||(a.value=b) +},a.enter=function(b){a.readonly||(a.val=b),a.onHover({value:b})},a.reset=function(){a.val=angular.copy(a.value),a.onLeave()},a.$watch("value",function(b){a.val=b}),a.readonly=!1,b.readonly&&a.$parent.$watch(c(b.readonly),function(b){a.readonly=!!b})}]).directive("rating",function(){return{restrict:"EA",scope:{value:"=",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(a){a.active=!1}),a.active=!0},b.addTab=function(a){c.push(a),(1===c.length||a.active)&&b.select(a)},b.removeTab=function(a){var d=c.indexOf(a);if(a.active&&c.length>1){var e=d==c.length-1?d-1:d+1;b.select(c[e])}c.splice(d,1)}}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1,a.type=angular.isDefined(c.type)?a.$parent.$eval(c.type):"tabs"}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){var g,h;e.active?(g=a(e.active),h=g.assign,b.$parent.$watch(g,function(a,c){a!==c&&(b.active=!!a)}),b.active=g(b.$parent)):h=g=angular.noop,b.$watch("active",function(a){h(b.$parent,a),a?(f.select(b),b.onSelect()):b.onDeselect()}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).directive("timepicker",["$parse","$log","timepickerConfig","$locale",function(a,b,c,d){return{restrict:"EA",require:"?^ngModel",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(e,f,g,h){function i(){var a=parseInt(e.hours,10),b=e.showMeridian?a>0&&13>a:a>=0&&24>a;return b?(e.showMeridian&&(12===a&&(a=0),e.meridian===q[1]&&(a+=12)),a):void 0}function j(){var a=parseInt(e.minutes,10);return a>=0&&60>a?a:void 0}function k(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function l(a){m(),h.$setViewValue(new Date(p)),n(a)}function m(){h.$setValidity("time",!0),e.invalidHours=!1,e.invalidMinutes=!1}function n(a){var b=p.getHours(),c=p.getMinutes();e.showMeridian&&(b=0===b||12===b?12:b%12),e.hours="h"===a?b:k(b),e.minutes="m"===a?c:k(c),e.meridian=p.getHours()<12?q[0]:q[1]}function o(a){var b=new Date(p.getTime()+6e4*a);p.setHours(b.getHours(),b.getMinutes()),l()}if(h){var p=new Date,q=angular.isDefined(g.meridians)?e.$parent.$eval(g.meridians):c.meridians||d.DATETIME_FORMATS.AMPMS,r=c.hourStep;g.hourStep&&e.$parent.$watch(a(g.hourStep),function(a){r=parseInt(a,10)});var s=c.minuteStep;g.minuteStep&&e.$parent.$watch(a(g.minuteStep),function(a){s=parseInt(a,10)}),e.showMeridian=c.showMeridian,g.showMeridian&&e.$parent.$watch(a(g.showMeridian),function(a){if(e.showMeridian=!!a,h.$error.time){var b=i(),c=j();angular.isDefined(b)&&angular.isDefined(c)&&(p.setHours(b),l())}else n()});var t=f.find("input"),u=t.eq(0),v=t.eq(1),w=angular.isDefined(g.mousewheel)?e.$eval(g.mousewheel):c.mousewheel;if(w){var x=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};u.bind("mousewheel wheel",function(a){e.$apply(x(a)?e.incrementHours():e.decrementHours()),a.preventDefault()}),v.bind("mousewheel wheel",function(a){e.$apply(x(a)?e.incrementMinutes():e.decrementMinutes()),a.preventDefault()})}if(e.readonlyInput=angular.isDefined(g.readonlyInput)?e.$eval(g.readonlyInput):c.readonlyInput,e.readonlyInput)e.updateHours=angular.noop,e.updateMinutes=angular.noop;else{var y=function(a,b){h.$setViewValue(null),h.$setValidity("time",!1),angular.isDefined(a)&&(e.invalidHours=a),angular.isDefined(b)&&(e.invalidMinutes=b)};e.updateHours=function(){var a=i();angular.isDefined(a)?(p.setHours(a),l("h")):y(!0)},u.bind("blur",function(){!e.validHours&&e.hours<10&&e.$apply(function(){e.hours=k(e.hours)})}),e.updateMinutes=function(){var a=j();angular.isDefined(a)?(p.setMinutes(a),l("m")):y(void 0,!0)},v.bind("blur",function(){!e.invalidMinutes&&e.minutes<10&&e.$apply(function(){e.minutes=k(e.minutes)})})}h.$render=function(){var a=h.$modelValue?new Date(h.$modelValue):null;isNaN(a)?(h.$setValidity("time",!1),b.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(p=a),m(),n())},e.incrementHours=function(){o(60*r)},e.decrementHours=function(){o(60*-r)},e.incrementMinutes=function(){o(s)},e.decrementMinutes=function(){o(-s)},e.toggleMeridian=function(){o(720*(p.getHours()<12?1:-1))}}}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error("Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_' but got '"+c+"'.");return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?b(k.typeaheadAppendToBody):!1,u=b(k.ngModel).assign,v=g.parse(k.typeahead),w=angular.element("
      ");w.attr({matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&w.attr("template-url",k.typeaheadTemplateUrl);var x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y=function(){x.matches=[],x.activeIdx=-1},z=function(a){var b={$viewValue:a};q(i,!0),c.when(v.source(i,b)).then(function(c){if(a===l.$viewValue&&m){if(c.length>0){x.activeIdx=0,x.matches.length=0;for(var d=0;d=n?o>0?(A&&d.cancel(A),A=d(function(){z(a)},o)):z(a):(q(i,!1),y()),p?a:a?(l.$setValidity("editable",!1),void 0):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[v.itemName]=a,b=v.viewMapper(i,d),d[v.itemName]=void 0,c=v.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,d={};d[v.itemName]=c=x.matches[a].model,b=v.modelMapper(i,d),u(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:v.viewMapper(i,d)}),y(),j[0].focus()},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),y(),x.$digest()))}),j.bind("blur",function(){m=!1});var B=function(a){j[0]!==a.target&&(y(),x.$digest())};e.bind("click",B),i.$on("$destroy",function(){e.unbind("click",B)});var C=a(w)(x);t?e.find("body").append(C):j.after(C)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?b.replace(new RegExp(a(c),"gi"),"$&"):b}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'
      \n
      \n

      \n {{heading}}\n

      \n
      \n
      \n
      \n
      \n
      ')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'
      ')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html","
      \n \n
      \n
      \n")}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html","
      \n")}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
      #{{label}}
      {{ getWeekNumber(row) }}\n \n
      \n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html","
        \n
      • \n"+'
      • \n \n \n \n \n \n \n
      • \n
      \n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'
      \n
      \n
      \n
      \n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'
      \n
      \n
      \n
      \n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'
      \n
      \n\n
      \n

      \n
      \n
      \n
      \n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'
      ')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'
      ')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'
      ')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'\n \n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'
    • \n {{heading}}\n
    • \n')}]),angular.module("template/tabs/tabset-titles.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset-titles.html","
        \n
      \n")}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'\n
      \n \n
      \n
      \n
      \n
      \n
      \n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
       
      \n \n :\n \n
       
      \n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html","
        \n"+'
      • \n
        \n
      • \n
      ')}]); \ No newline at end of file diff --git a/dist/bower_components/angular-bootstrap/ui-bootstrap.js b/dist/bower_components/angular-bootstrap/ui-bootstrap.js new file mode 100644 index 000000000..deda5d087 --- /dev/null +++ b/dist/bower_components/angular-bootstrap/ui-bootstrap.js @@ -0,0 +1,3427 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.10.0 - 2014-01-13 + * License: MIT + */ +angular.module("ui.bootstrap", ["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]); +angular.module('ui.bootstrap.transition', []) + +/** + * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete. + * @param {DOMElement} element The DOMElement that will be animated. + * @param {string|object|function} trigger The thing that will cause the transition to start: + * - As a string, it represents the css class to be added to the element. + * - As an object, it represents a hash of style attributes to be applied to the element. + * - As a function, it represents a function to be called that will cause the transition to occur. + * @return {Promise} A promise that is resolved when the transition finishes. + */ +.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) { + + var $transition = function(element, trigger, options) { + options = options || {}; + var deferred = $q.defer(); + var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"]; + + var transitionEndHandler = function(event) { + $rootScope.$apply(function() { + element.unbind(endEventName, transitionEndHandler); + deferred.resolve(element); + }); + }; + + if (endEventName) { + element.bind(endEventName, transitionEndHandler); + } + + // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur + $timeout(function() { + if ( angular.isString(trigger) ) { + element.addClass(trigger); + } else if ( angular.isFunction(trigger) ) { + trigger(element); + } else if ( angular.isObject(trigger) ) { + element.css(trigger); + } + //If browser does not support transitions, instantly resolve + if ( !endEventName ) { + deferred.resolve(element); + } + }); + + // Add our custom cancel function to the promise that is returned + // We can call this if we are about to run a new transition, which we know will prevent this transition from ending, + // i.e. it will therefore never raise a transitionEnd event for that transition + deferred.promise.cancel = function() { + if ( endEventName ) { + element.unbind(endEventName, transitionEndHandler); + } + deferred.reject('Transition cancelled'); + }; + + return deferred.promise; + }; + + // Work out the name of the transitionEnd event + var transElement = document.createElement('trans'); + var transitionEndEventNames = { + 'WebkitTransition': 'webkitTransitionEnd', + 'MozTransition': 'transitionend', + 'OTransition': 'oTransitionEnd', + 'transition': 'transitionend' + }; + var animationEndEventNames = { + 'WebkitTransition': 'webkitAnimationEnd', + 'MozTransition': 'animationend', + 'OTransition': 'oAnimationEnd', + 'transition': 'animationend' + }; + function findEndEventName(endEventNames) { + for (var name in endEventNames){ + if (transElement.style[name] !== undefined) { + return endEventNames[name]; + } + } + } + $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); + $transition.animationEndEventName = findEndEventName(animationEndEventNames); + return $transition; +}]); + +angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition']) + + .directive('collapse', ['$transition', function ($transition, $timeout) { + + return { + link: function (scope, element, attrs) { + + var initialAnimSkip = true; + var currentTransition; + + function doTransition(change) { + var newTransition = $transition(element, change); + if (currentTransition) { + currentTransition.cancel(); + } + currentTransition = newTransition; + newTransition.then(newTransitionDone, newTransitionDone); + return newTransition; + + function newTransitionDone() { + // Make sure it's this transition, otherwise, leave it alone. + if (currentTransition === newTransition) { + currentTransition = undefined; + } + } + } + + function expand() { + if (initialAnimSkip) { + initialAnimSkip = false; + expandDone(); + } else { + element.removeClass('collapse').addClass('collapsing'); + doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone); + } + } + + function expandDone() { + element.removeClass('collapsing'); + element.addClass('collapse in'); + element.css({height: 'auto'}); + } + + function collapse() { + if (initialAnimSkip) { + initialAnimSkip = false; + collapseDone(); + element.css({height: 0}); + } else { + // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value + element.css({ height: element[0].scrollHeight + 'px' }); + //trigger reflow so a browser realizes that height was updated from auto to a specific value + var x = element[0].offsetWidth; + + element.removeClass('collapse in').addClass('collapsing'); + + doTransition({ height: 0 }).then(collapseDone); + } + } + + function collapseDone() { + element.removeClass('collapsing'); + element.addClass('collapse'); + } + + scope.$watch(attrs.collapse, function (shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); + } + }; + }]); + +angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) + +.constant('accordionConfig', { + closeOthers: true +}) + +.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) { + + // This array keeps track of the accordion groups + this.groups = []; + + // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to + this.closeOthers = function(openGroup) { + var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; + if ( closeOthers ) { + angular.forEach(this.groups, function (group) { + if ( group !== openGroup ) { + group.isOpen = false; + } + }); + } + }; + + // This is called from the accordion-group directive to add itself to the accordion + this.addGroup = function(groupScope) { + var that = this; + this.groups.push(groupScope); + + groupScope.$on('$destroy', function (event) { + that.removeGroup(groupScope); + }); + }; + + // This is called from the accordion-group directive when to remove itself + this.removeGroup = function(group) { + var index = this.groups.indexOf(group); + if ( index !== -1 ) { + this.groups.splice(this.groups.indexOf(group), 1); + } + }; + +}]) + +// The accordion directive simply sets up the directive controller +// and adds an accordion CSS class to itself element. +.directive('accordion', function () { + return { + restrict:'EA', + controller:'AccordionController', + transclude: true, + replace: false, + templateUrl: 'template/accordion/accordion.html' + }; +}) + +// The accordion-group directive indicates a block of html that will expand and collapse in an accordion +.directive('accordionGroup', ['$parse', function($parse) { + return { + require:'^accordion', // We need this directive to be inside an accordion + restrict:'EA', + transclude:true, // It transcludes the contents of the directive into the template + replace: true, // The element containing the directive will be replaced with the template + templateUrl:'template/accordion/accordion-group.html', + scope:{ heading:'@' }, // Create an isolated scope and interpolate the heading attribute onto this scope + controller: function() { + this.setHeading = function(element) { + this.heading = element; + }; + }, + link: function(scope, element, attrs, accordionCtrl) { + var getIsOpen, setIsOpen; + + accordionCtrl.addGroup(scope); + + scope.isOpen = false; + + if ( attrs.isOpen ) { + getIsOpen = $parse(attrs.isOpen); + setIsOpen = getIsOpen.assign; + + scope.$parent.$watch(getIsOpen, function(value) { + scope.isOpen = !!value; + }); + } + + scope.$watch('isOpen', function(value) { + if ( value ) { + accordionCtrl.closeOthers(scope); + } + if ( setIsOpen ) { + setIsOpen(scope.$parent, value); + } + }); + } + }; +}]) + +// Use accordion-heading below an accordion-group to provide a heading containing HTML +// +// Heading containing HTML - +// +.directive('accordionHeading', function() { + return { + restrict: 'EA', + transclude: true, // Grab the contents to be used as the heading + template: '', // In effect remove this element! + replace: true, + require: '^accordionGroup', + compile: function(element, attr, transclude) { + return function link(scope, element, attr, accordionGroupCtrl) { + // Pass the heading to the accordion-group controller + // so that it can be transcluded into the right place in the template + // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat] + accordionGroupCtrl.setHeading(transclude(scope, function() {})); + }; + } + }; +}) + +// Use in the accordion-group template to indicate where you want the heading to be transcluded +// You must provide the property on the accordion-group controller that will hold the transcluded element +//
      +// +// ... +//
      +.directive('accordionTransclude', function() { + return { + require: '^accordionGroup', + link: function(scope, element, attr, controller) { + scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) { + if ( heading ) { + element.html(''); + element.append(heading); + } + }); + } + }; +}); + +angular.module("ui.bootstrap.alert", []) + +.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) { + $scope.closeable = 'close' in $attrs; +}]) + +.directive('alert', function () { + return { + restrict:'EA', + controller:'AlertController', + templateUrl:'template/alert/alert.html', + transclude:true, + replace:true, + scope: { + type: '=', + close: '&' + } + }; +}); + +angular.module('ui.bootstrap.bindHtml', []) + + .directive('bindHtmlUnsafe', function () { + return function (scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ''); + }); + }; + }); +angular.module('ui.bootstrap.buttons', []) + +.constant('buttonConfig', { + activeClass: 'active', + toggleEvent: 'click' +}) + +.controller('ButtonsController', ['buttonConfig', function(buttonConfig) { + this.activeClass = buttonConfig.activeClass || 'active'; + this.toggleEvent = buttonConfig.toggleEvent || 'click'; +}]) + +.directive('btnRadio', function () { + return { + require: ['btnRadio', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + if (!element.hasClass(buttonsCtrl.activeClass)) { + scope.$apply(function () { + ngModelCtrl.$setViewValue(scope.$eval(attrs.btnRadio)); + ngModelCtrl.$render(); + }); + } + }); + } + }; +}) + +.directive('btnCheckbox', function () { + return { + require: ['btnCheckbox', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + function getTrueValue() { + return getCheckboxValue(attrs.btnCheckboxTrue, true); + } + + function getFalseValue() { + return getCheckboxValue(attrs.btnCheckboxFalse, false); + } + + function getCheckboxValue(attributeValue, defaultValue) { + var val = scope.$eval(attributeValue); + return angular.isDefined(val) ? val : defaultValue; + } + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + scope.$apply(function () { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); + }); + }); + } + }; +}); + +/** +* @ngdoc overview +* @name ui.bootstrap.carousel +* +* @description +* AngularJS version of an image carousel. +* +*/ +angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) +.controller('CarouselController', ['$scope', '$timeout', '$transition', '$q', function ($scope, $timeout, $transition, $q) { + var self = this, + slides = self.slides = [], + currentIndex = -1, + currentTimeout, isPlaying; + self.currentSlide = null; + + var destroyed = false; + /* direction: "prev" or "next" */ + self.select = function(nextSlide, direction) { + var nextIndex = slides.indexOf(nextSlide); + //Decide direction if it's not given + if (direction === undefined) { + direction = nextIndex > currentIndex ? "next" : "prev"; + } + if (nextSlide && nextSlide !== self.currentSlide) { + if ($scope.$currentTransition) { + $scope.$currentTransition.cancel(); + //Timeout so ng-class in template has time to fix classes for finished slide + $timeout(goNext); + } else { + goNext(); + } + } + function goNext() { + // Scope has been destroyed, stop here. + if (destroyed) { return; } + //If we have a slide to transition from and we have a transition type and we're allowed, go + if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) { + //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime + nextSlide.$element.addClass(direction); + var reflow = nextSlide.$element[0].offsetWidth; //force reflow + + //Set all other slides to stop doing their stuff for the new transition + angular.forEach(slides, function(slide) { + angular.extend(slide, {direction: '', entering: false, leaving: false, active: false}); + }); + angular.extend(nextSlide, {direction: direction, active: true, entering: true}); + angular.extend(self.currentSlide||{}, {direction: direction, leaving: true}); + + $scope.$currentTransition = $transition(nextSlide.$element, {}); + //We have to create new pointers inside a closure since next & current will change + (function(next,current) { + $scope.$currentTransition.then( + function(){ transitionDone(next, current); }, + function(){ transitionDone(next, current); } + ); + }(nextSlide, self.currentSlide)); + } else { + transitionDone(nextSlide, self.currentSlide); + } + self.currentSlide = nextSlide; + currentIndex = nextIndex; + //every time you change slides, reset the timer + restartTimer(); + } + function transitionDone(next, current) { + angular.extend(next, {direction: '', active: true, leaving: false, entering: false}); + angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false}); + $scope.$currentTransition = null; + } + }; + $scope.$on('$destroy', function () { + destroyed = true; + }); + + /* Allow outside people to call indexOf on slides array */ + self.indexOfSlide = function(slide) { + return slides.indexOf(slide); + }; + + $scope.next = function() { + var newIndex = (currentIndex + 1) % slides.length; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(slides[newIndex], 'next'); + } + }; + + $scope.prev = function() { + var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(slides[newIndex], 'prev'); + } + }; + + $scope.select = function(slide) { + self.select(slide); + }; + + $scope.isActive = function(slide) { + return self.currentSlide === slide; + }; + + $scope.slides = function() { + return slides; + }; + + $scope.$watch('interval', restartTimer); + $scope.$on('$destroy', resetTimer); + + function restartTimer() { + resetTimer(); + var interval = +$scope.interval; + if (!isNaN(interval) && interval>=0) { + currentTimeout = $timeout(timerFn, interval); + } + } + + function resetTimer() { + if (currentTimeout) { + $timeout.cancel(currentTimeout); + currentTimeout = null; + } + } + + function timerFn() { + if (isPlaying) { + $scope.next(); + restartTimer(); + } else { + $scope.pause(); + } + } + + $scope.play = function() { + if (!isPlaying) { + isPlaying = true; + restartTimer(); + } + }; + $scope.pause = function() { + if (!$scope.noPause) { + isPlaying = false; + resetTimer(); + } + }; + + self.addSlide = function(slide, element) { + slide.$element = element; + slides.push(slide); + //if this is the first slide or the slide is set to active, select it + if(slides.length === 1 || slide.active) { + self.select(slides[slides.length-1]); + if (slides.length == 1) { + $scope.play(); + } + } else { + slide.active = false; + } + }; + + self.removeSlide = function(slide) { + //get the index of the slide inside the carousel + var index = slides.indexOf(slide); + slides.splice(index, 1); + if (slides.length > 0 && slide.active) { + if (index >= slides.length) { + self.select(slides[index-1]); + } else { + self.select(slides[index]); + } + } else if (currentIndex > index) { + currentIndex--; + } + }; + +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:carousel + * @restrict EA + * + * @description + * Carousel is the outer container for a set of image 'slides' to showcase. + * + * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide. + * @param {boolean=} noTransition Whether to disable transitions on the carousel. + * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover). + * + * @example + + + + + + + + + + + + + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + + + */ +.directive('carousel', [function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + controller: 'CarouselController', + require: 'carousel', + templateUrl: 'template/carousel/carousel.html', + scope: { + interval: '=', + noTransition: '=', + noPause: '=' + } + }; +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:slide + * @restrict EA + * + * @description + * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}. Must be placed as a child of a carousel element. + * + * @param {boolean=} active Model binding, whether or not this slide is currently active. + * + * @example + + +
      + + + + + + +
      +
      +
        +
      • + + {{$index}}: {{slide.text}} +
      • +
      + Add Slide +
      +
      + Interval, in milliseconds: +
      Enter a negative number to stop the interval. +
      +
      +
      +
      + +function CarouselDemoCtrl($scope) { + $scope.myInterval = 5000; + var slides = $scope.slides = []; + $scope.addSlide = function() { + var newWidth = 200 + ((slides.length + (25 * slides.length)) % 150); + slides.push({ + image: 'http://placekitten.com/' + newWidth + '/200', + text: ['More','Extra','Lots of','Surplus'][slides.length % 4] + ' ' + ['Cats', 'Kittys', 'Felines', 'Cutes'][slides.length % 4] + }); + }; + for (var i=0; i<4; i++) $scope.addSlide(); +} + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + +
      +*/ + +.directive('slide', ['$parse', function($parse) { + return { + require: '^carousel', + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'template/carousel/slide.html', + scope: { + }, + link: function (scope, element, attrs, carouselCtrl) { + //Set up optional 'active' = binding + if (attrs.active) { + var getActive = $parse(attrs.active); + var setActive = getActive.assign; + var lastValue = scope.active = getActive(scope.$parent); + scope.$watch(function parentActiveWatch() { + var parentActive = getActive(scope.$parent); + + if (parentActive !== scope.active) { + // we are out of sync and need to copy + if (parentActive !== lastValue) { + // parent changed and it has precedence + lastValue = scope.active = parentActive; + } else { + // if the parent can be assigned then do so + setActive(scope.$parent, parentActive = lastValue = scope.active); + } + } + return parentActive; + }); + } + + carouselCtrl.addSlide(scope, element); + //when the scope is destroyed then remove the slide from the current slides array + scope.$on('$destroy', function() { + carouselCtrl.removeSlide(scope); + }); + + scope.$watch('active', function(active) { + if (active) { + carouselCtrl.select(scope); + } + }); + } + }; +}]); + +angular.module('ui.bootstrap.position', []) + +/** + * A set of utility methods that can be use to retrieve position of DOM elements. + * It is meant to be used where we need to absolute-position DOM elements in + * relation to other, existing elements (this is the case for tooltips, popovers, + * typeahead suggestions etc.). + */ + .factory('$position', ['$document', '$window', function ($document, $window) { + + function getStyle(el, cssprop) { + if (el.currentStyle) { //IE + return el.currentStyle[cssprop]; + } else if ($window.getComputedStyle) { + return $window.getComputedStyle(el)[cssprop]; + } + // finally try and get inline style + return el.style[cssprop]; + } + + /** + * Checks if a given element is statically positioned + * @param element - raw DOM element + */ + function isStaticPositioned(element) { + return (getStyle(element, "position") || 'static' ) === 'static'; + } + + /** + * returns the closest, non-statically positioned parentOffset of a given element + * @param element + */ + var parentOffsetEl = function (element) { + var docDomEl = $document[0]; + var offsetParent = element.offsetParent || docDomEl; + while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docDomEl; + }; + + return { + /** + * Provides read-only equivalent of jQuery's position function: + * http://api.jquery.com/position/ + */ + position: function (element) { + var elBCR = this.offset(element); + var offsetParentBCR = { top: 0, left: 0 }; + var offsetParentEl = parentOffsetEl(element[0]); + if (offsetParentEl != $document[0]) { + offsetParentBCR = this.offset(angular.element(offsetParentEl)); + offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; + offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; + } + + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: elBCR.top - offsetParentBCR.top, + left: elBCR.left - offsetParentBCR.left + }; + }, + + /** + * Provides read-only equivalent of jQuery's offset function: + * http://api.jquery.com/offset/ + */ + offset: function (element) { + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft) + }; + } + }; + }]); + +angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.position']) + +.constant('datepickerConfig', { + dayFormat: 'dd', + monthFormat: 'MMMM', + yearFormat: 'yyyy', + dayHeaderFormat: 'EEE', + dayTitleFormat: 'MMMM yyyy', + monthTitleFormat: 'yyyy', + showWeeks: true, + startingDay: 0, + yearRange: 20, + minDate: null, + maxDate: null +}) + +.controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) { + var format = { + day: getValue($attrs.dayFormat, dtConfig.dayFormat), + month: getValue($attrs.monthFormat, dtConfig.monthFormat), + year: getValue($attrs.yearFormat, dtConfig.yearFormat), + dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat), + dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat), + monthTitle: getValue($attrs.monthTitleFormat, dtConfig.monthTitleFormat) + }, + startingDay = getValue($attrs.startingDay, dtConfig.startingDay), + yearRange = getValue($attrs.yearRange, dtConfig.yearRange); + + this.minDate = dtConfig.minDate ? new Date(dtConfig.minDate) : null; + this.maxDate = dtConfig.maxDate ? new Date(dtConfig.maxDate) : null; + + function getValue(value, defaultValue) { + return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue; + } + + function getDaysInMonth( year, month ) { + return new Date(year, month, 0).getDate(); + } + + function getDates(startDate, n) { + var dates = new Array(n); + var current = startDate, i = 0; + while (i < n) { + dates[i++] = new Date(current); + current.setDate( current.getDate() + 1 ); + } + return dates; + } + + function makeDate(date, format, isSelected, isSecondary) { + return { date: date, label: dateFilter(date, format), selected: !!isSelected, secondary: !!isSecondary }; + } + + this.modes = [ + { + name: 'day', + getVisibleDates: function(date, selected) { + var year = date.getFullYear(), month = date.getMonth(), firstDayOfMonth = new Date(year, month, 1); + var difference = startingDay - firstDayOfMonth.getDay(), + numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference, + firstDate = new Date(firstDayOfMonth), numDates = 0; + + if ( numDisplayedFromPreviousMonth > 0 ) { + firstDate.setDate( - numDisplayedFromPreviousMonth + 1 ); + numDates += numDisplayedFromPreviousMonth; // Previous + } + numDates += getDaysInMonth(year, month + 1); // Current + numDates += (7 - numDates % 7) % 7; // Next + + var days = getDates(firstDate, numDates), labels = new Array(7); + for (var i = 0; i < numDates; i ++) { + var dt = new Date(days[i]); + days[i] = makeDate(dt, format.day, (selected && selected.getDate() === dt.getDate() && selected.getMonth() === dt.getMonth() && selected.getFullYear() === dt.getFullYear()), dt.getMonth() !== month); + } + for (var j = 0; j < 7; j++) { + labels[j] = dateFilter(days[j].date, format.dayHeader); + } + return { objects: days, title: dateFilter(date, format.dayTitle), labels: labels }; + }, + compare: function(date1, date2) { + return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) ); + }, + split: 7, + step: { months: 1 } + }, + { + name: 'month', + getVisibleDates: function(date, selected) { + var months = new Array(12), year = date.getFullYear(); + for ( var i = 0; i < 12; i++ ) { + var dt = new Date(year, i, 1); + months[i] = makeDate(dt, format.month, (selected && selected.getMonth() === i && selected.getFullYear() === year)); + } + return { objects: months, title: dateFilter(date, format.monthTitle) }; + }, + compare: function(date1, date2) { + return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() ); + }, + split: 3, + step: { years: 1 } + }, + { + name: 'year', + getVisibleDates: function(date, selected) { + var years = new Array(yearRange), year = date.getFullYear(), startYear = parseInt((year - 1) / yearRange, 10) * yearRange + 1; + for ( var i = 0; i < yearRange; i++ ) { + var dt = new Date(startYear + i, 0, 1); + years[i] = makeDate(dt, format.year, (selected && selected.getFullYear() === dt.getFullYear())); + } + return { objects: years, title: [years[0].label, years[yearRange - 1].label].join(' - ') }; + }, + compare: function(date1, date2) { + return date1.getFullYear() - date2.getFullYear(); + }, + split: 5, + step: { years: yearRange } + } + ]; + + this.isDisabled = function(date, mode) { + var currentMode = this.modes[mode || 0]; + return ((this.minDate && currentMode.compare(date, this.minDate) < 0) || (this.maxDate && currentMode.compare(date, this.maxDate) > 0) || ($scope.dateDisabled && $scope.dateDisabled({date: date, mode: currentMode.name}))); + }; +}]) + +.directive( 'datepicker', ['dateFilter', '$parse', 'datepickerConfig', '$log', function (dateFilter, $parse, datepickerConfig, $log) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/datepicker.html', + scope: { + dateDisabled: '&' + }, + require: ['datepicker', '?^ngModel'], + controller: 'DatepickerController', + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0], ngModel = ctrls[1]; + + if (!ngModel) { + return; // do nothing if no ng-model + } + + // Configuration parameters + var mode = 0, selected = new Date(), showWeeks = datepickerConfig.showWeeks; + + if (attrs.showWeeks) { + scope.$parent.$watch($parse(attrs.showWeeks), function(value) { + showWeeks = !! value; + updateShowWeekNumbers(); + }); + } else { + updateShowWeekNumbers(); + } + + if (attrs.min) { + scope.$parent.$watch($parse(attrs.min), function(value) { + datepickerCtrl.minDate = value ? new Date(value) : null; + refill(); + }); + } + if (attrs.max) { + scope.$parent.$watch($parse(attrs.max), function(value) { + datepickerCtrl.maxDate = value ? new Date(value) : null; + refill(); + }); + } + + function updateShowWeekNumbers() { + scope.showWeekNumbers = mode === 0 && showWeeks; + } + + // Split array into smaller arrays + function split(arr, size) { + var arrays = []; + while (arr.length > 0) { + arrays.push(arr.splice(0, size)); + } + return arrays; + } + + function refill( updateSelected ) { + var date = null, valid = true; + + if ( ngModel.$modelValue ) { + date = new Date( ngModel.$modelValue ); + + if ( isNaN(date) ) { + valid = false; + $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else if ( updateSelected ) { + selected = date; + } + } + ngModel.$setValidity('date', valid); + + var currentMode = datepickerCtrl.modes[mode], data = currentMode.getVisibleDates(selected, date); + angular.forEach(data.objects, function(obj) { + obj.disabled = datepickerCtrl.isDisabled(obj.date, mode); + }); + + ngModel.$setValidity('date-disabled', (!date || !datepickerCtrl.isDisabled(date))); + + scope.rows = split(data.objects, currentMode.split); + scope.labels = data.labels || []; + scope.title = data.title; + } + + function setMode(value) { + mode = value; + updateShowWeekNumbers(); + refill(); + } + + ngModel.$render = function() { + refill( true ); + }; + + scope.select = function( date ) { + if ( mode === 0 ) { + var dt = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0); + dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() ); + ngModel.$setViewValue( dt ); + refill( true ); + } else { + selected = date; + setMode( mode - 1 ); + } + }; + scope.move = function(direction) { + var step = datepickerCtrl.modes[mode].step; + selected.setMonth( selected.getMonth() + direction * (step.months || 0) ); + selected.setFullYear( selected.getFullYear() + direction * (step.years || 0) ); + refill(); + }; + scope.toggleMode = function() { + setMode( (mode + 1) % datepickerCtrl.modes.length ); + }; + scope.getWeekNumber = function(row) { + return ( mode === 0 && scope.showWeekNumbers && row.length === 7 ) ? getISO8601WeekNumber(row[0].date) : null; + }; + + function getISO8601WeekNumber(date) { + var checkDate = new Date(date); + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + } + } + }; +}]) + +.constant('datepickerPopupConfig', { + dateFormat: 'yyyy-MM-dd', + currentText: 'Today', + toggleWeeksText: 'Weeks', + clearText: 'Clear', + closeText: 'Done', + closeOnDateSelection: true, + appendToBody: false, + showButtonBar: true +}) + +.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'datepickerPopupConfig', 'datepickerConfig', +function ($compile, $parse, $document, $position, dateFilter, datepickerPopupConfig, datepickerConfig) { + return { + restrict: 'EA', + require: 'ngModel', + link: function(originalScope, element, attrs, ngModel) { + var scope = originalScope.$new(), // create a child scope so we are not polluting original one + dateFormat, + closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? originalScope.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, + appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? originalScope.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody; + + attrs.$observe('datepickerPopup', function(value) { + dateFormat = value || datepickerPopupConfig.dateFormat; + ngModel.$render(); + }); + + scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? originalScope.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; + + originalScope.$on('$destroy', function() { + $popup.remove(); + scope.$destroy(); + }); + + attrs.$observe('currentText', function(text) { + scope.currentText = angular.isDefined(text) ? text : datepickerPopupConfig.currentText; + }); + attrs.$observe('toggleWeeksText', function(text) { + scope.toggleWeeksText = angular.isDefined(text) ? text : datepickerPopupConfig.toggleWeeksText; + }); + attrs.$observe('clearText', function(text) { + scope.clearText = angular.isDefined(text) ? text : datepickerPopupConfig.clearText; + }); + attrs.$observe('closeText', function(text) { + scope.closeText = angular.isDefined(text) ? text : datepickerPopupConfig.closeText; + }); + + var getIsOpen, setIsOpen; + if ( attrs.isOpen ) { + getIsOpen = $parse(attrs.isOpen); + setIsOpen = getIsOpen.assign; + + originalScope.$watch(getIsOpen, function updateOpen(value) { + scope.isOpen = !! value; + }); + } + scope.isOpen = getIsOpen ? getIsOpen(originalScope) : false; // Initial state + + function setOpen( value ) { + if (setIsOpen) { + setIsOpen(originalScope, !!value); + } else { + scope.isOpen = !!value; + } + } + + var documentClickBind = function(event) { + if (scope.isOpen && event.target !== element[0]) { + scope.$apply(function() { + setOpen(false); + }); + } + }; + + var elementFocusBind = function() { + scope.$apply(function() { + setOpen( true ); + }); + }; + + // popup element used to display calendar + var popupEl = angular.element('
      '); + popupEl.attr({ + 'ng-model': 'date', + 'ng-change': 'dateSelection()' + }); + var datepickerEl = angular.element(popupEl.children()[0]), + datepickerOptions = {}; + if (attrs.datepickerOptions) { + datepickerOptions = originalScope.$eval(attrs.datepickerOptions); + datepickerEl.attr(angular.extend({}, datepickerOptions)); + } + + // TODO: reverse from dateFilter string to Date object + function parseDate(viewValue) { + if (!viewValue) { + ngModel.$setValidity('date', true); + return null; + } else if (angular.isDate(viewValue)) { + ngModel.$setValidity('date', true); + return viewValue; + } else if (angular.isString(viewValue)) { + var date = new Date(viewValue); + if (isNaN(date)) { + ngModel.$setValidity('date', false); + return undefined; + } else { + ngModel.$setValidity('date', true); + return date; + } + } else { + ngModel.$setValidity('date', false); + return undefined; + } + } + ngModel.$parsers.unshift(parseDate); + + // Inner change + scope.dateSelection = function(dt) { + if (angular.isDefined(dt)) { + scope.date = dt; + } + ngModel.$setViewValue(scope.date); + ngModel.$render(); + + if (closeOnDateSelection) { + setOpen( false ); + } + }; + + element.bind('input change keyup', function() { + scope.$apply(function() { + scope.date = ngModel.$modelValue; + }); + }); + + // Outter change + ngModel.$render = function() { + var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : ''; + element.val(date); + scope.date = ngModel.$modelValue; + }; + + function addWatchableAttribute(attribute, scopeProperty, datepickerAttribute) { + if (attribute) { + originalScope.$watch($parse(attribute), function(value){ + scope[scopeProperty] = value; + }); + datepickerEl.attr(datepickerAttribute || scopeProperty, scopeProperty); + } + } + addWatchableAttribute(attrs.min, 'min'); + addWatchableAttribute(attrs.max, 'max'); + if (attrs.showWeeks) { + addWatchableAttribute(attrs.showWeeks, 'showWeeks', 'show-weeks'); + } else { + scope.showWeeks = 'show-weeks' in datepickerOptions ? datepickerOptions['show-weeks'] : datepickerConfig.showWeeks; + datepickerEl.attr('show-weeks', 'showWeeks'); + } + if (attrs.dateDisabled) { + datepickerEl.attr('date-disabled', attrs.dateDisabled); + } + + function updatePosition() { + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop('offsetHeight'); + } + + var documentBindingInitialized = false, elementFocusInitialized = false; + scope.$watch('isOpen', function(value) { + if (value) { + updatePosition(); + $document.bind('click', documentClickBind); + if(elementFocusInitialized) { + element.unbind('focus', elementFocusBind); + } + element[0].focus(); + documentBindingInitialized = true; + } else { + if(documentBindingInitialized) { + $document.unbind('click', documentClickBind); + } + element.bind('focus', elementFocusBind); + elementFocusInitialized = true; + } + + if ( setIsOpen ) { + setIsOpen(originalScope, value); + } + }); + + scope.today = function() { + scope.dateSelection(new Date()); + }; + scope.clear = function() { + scope.dateSelection(null); + }; + + var $popup = $compile(popupEl)(scope); + if ( appendToBody ) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + } + }; +}]) + +.directive('datepickerPopupWrap', function() { + return { + restrict:'EA', + replace: true, + transclude: true, + templateUrl: 'template/datepicker/popup.html', + link:function (scope, element, attrs) { + element.bind('click', function(event) { + event.preventDefault(); + event.stopPropagation(); + }); + } + }; +}); + +/* + * dropdownToggle - Provides dropdown menu functionality in place of bootstrap js + * @restrict class or attribute + * @example: + + */ + +angular.module('ui.bootstrap.dropdownToggle', []).directive('dropdownToggle', ['$document', '$location', function ($document, $location) { + var openElement = null, + closeMenu = angular.noop; + return { + restrict: 'CA', + link: function(scope, element, attrs) { + scope.$watch('$location.path', function() { closeMenu(); }); + element.parent().bind('click', function() { closeMenu(); }); + element.bind('click', function (event) { + + var elementWasOpen = (element === openElement); + + event.preventDefault(); + event.stopPropagation(); + + if (!!openElement) { + closeMenu(); + } + + if (!elementWasOpen && !element.hasClass('disabled') && !element.prop('disabled')) { + element.parent().addClass('open'); + openElement = element; + closeMenu = function (event) { + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + $document.unbind('click', closeMenu); + element.parent().removeClass('open'); + closeMenu = angular.noop; + openElement = null; + }; + $document.bind('click', closeMenu); + } + }); + } + }; +}]); + +angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition']) + +/** + * A helper, internal data structure that acts as a map but also allows getting / removing + * elements in the LIFO order + */ + .factory('$$stackedMap', function () { + return { + createNew: function () { + var stack = []; + + return { + add: function (key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function (key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function () { + return stack[stack.length - 1]; + }, + remove: function (key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } + } + return stack.splice(idx, 1)[0]; + }, + removeTop: function () { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function () { + return stack.length; + } + }; + } + }; + }) + +/** + * A helper directive for the $modal service. It creates a backdrop element. + */ + .directive('modalBackdrop', ['$timeout', function ($timeout) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/modal/backdrop.html', + link: function (scope) { + + scope.animate = false; + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + } + }; + }]) + + .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) { + return { + restrict: 'EA', + scope: { + index: '@', + animate: '=' + }, + replace: true, + transclude: true, + templateUrl: 'template/modal/window.html', + link: function (scope, element, attrs) { + scope.windowClass = attrs.windowClass || ''; + + $timeout(function () { + // trigger CSS transitions + scope.animate = true; + // focus a freshly-opened modal + element[0].focus(); + }); + + scope.close = function (evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, 'backdrop click'); + } + }; + } + }; + }]) + + .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap', + function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) { + + var OPENED_MODAL_CLASS = 'modal-open'; + + var backdropDomEl, backdropScope; + var openedWindows = $$stackedMap.createNew(); + var $modalStack = {}; + + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; + } + } + return topBackdropIndex; + } + + $rootScope.$watch(backdropIndex, function(newBackdropIndex){ + if (backdropScope) { + backdropScope.index = newBackdropIndex; + } + }); + + function removeModalWindow(modalInstance) { + + var body = $document.find('body').eq(0); + var modalWindow = openedWindows.get(modalInstance).value; + + //clean up the stack + openedWindows.remove(modalInstance); + + //remove window DOM element + removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, checkRemoveBackdrop); + body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0); + } + + function checkRemoveBackdrop() { + //remove backdrop if no longer needed + if (backdropDomEl && backdropIndex() == -1) { + var backdropScopeRef = backdropScope; + removeAfterAnimate(backdropDomEl, backdropScope, 150, function () { + backdropScopeRef.$destroy(); + backdropScopeRef = null; + }); + backdropDomEl = undefined; + backdropScope = undefined; + } + } + + function removeAfterAnimate(domEl, scope, emulateTime, done) { + // Closing animation + scope.animate = false; + + var transitionEndEventName = $transition.transitionEndEventName; + if (transitionEndEventName) { + // transition out + var timeout = $timeout(afterAnimating, emulateTime); + + domEl.bind(transitionEndEventName, function () { + $timeout.cancel(timeout); + afterAnimating(); + scope.$apply(); + }); + } else { + // Ensure this call is async + $timeout(afterAnimating, 0); + } + + function afterAnimating() { + if (afterAnimating.done) { + return; + } + afterAnimating.done = true; + + domEl.remove(); + if (done) { + done(); + } + } + } + + $document.bind('keydown', function (evt) { + var modal; + + if (evt.which === 27) { + modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + $rootScope.$apply(function () { + $modalStack.dismiss(modal.key); + }); + } + } + }); + + $modalStack.open = function (modalInstance, modal) { + + openedWindows.add(modalInstance, { + deferred: modal.deferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard + }); + + var body = $document.find('body').eq(0), + currBackdropIndex = backdropIndex(); + + if (currBackdropIndex >= 0 && !backdropDomEl) { + backdropScope = $rootScope.$new(true); + backdropScope.index = currBackdropIndex; + backdropDomEl = $compile('
      ')(backdropScope); + body.append(backdropDomEl); + } + + var angularDomEl = angular.element('
      '); + angularDomEl.attr('window-class', modal.windowClass); + angularDomEl.attr('index', openedWindows.length() - 1); + angularDomEl.attr('animate', 'animate'); + angularDomEl.html(modal.content); + + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + body.append(modalDomEl); + body.addClass(OPENED_MODAL_CLASS); + }; + + $modalStack.close = function (modalInstance, result) { + var modalWindow = openedWindows.get(modalInstance).value; + if (modalWindow) { + modalWindow.deferred.resolve(result); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismiss = function (modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance).value; + if (modalWindow) { + modalWindow.deferred.reject(reason); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismissAll = function (reason) { + var topModal = this.getTop(); + while (topModal) { + this.dismiss(topModal.key, reason); + topModal = this.getTop(); + } + }; + + $modalStack.getTop = function () { + return openedWindows.top(); + }; + + return $modalStack; + }]) + + .provider('$modal', function () { + + var $modalProvider = { + options: { + backdrop: true, //can be also false or 'static' + keyboard: true + }, + $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack', + function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) { + + var $modal = {}; + + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : + $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) { + return result.data; + }); + } + + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function (value, key) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } + }); + return promisesArr; + } + + $modal.open = function (modalOptions) { + + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + + //prepare an instance of a modal to be injected into controllers and returned to a caller + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + close: function (result) { + $modalStack.close(modalInstance, result); + }, + dismiss: function (reason) { + $modalStack.dismiss(modalInstance, reason); + } + }; + + //merge and clean up options + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + + //verify options + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error('One of template or templateUrl options is required.'); + } + + var templateAndResolvePromise = + $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve))); + + + templateAndResolvePromise.then(function resolveSuccess(tplAndVars) { + + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + + //controllers + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function (value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + } + + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + content: tplAndVars[0], + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + windowClass: modalOptions.windowClass + }); + + }, function resolveError(reason) { + modalResultDeferred.reject(reason); + }); + + templateAndResolvePromise.then(function () { + modalOpenedDeferred.resolve(true); + }, function () { + modalOpenedDeferred.reject(false); + }); + + return modalInstance; + }; + + return $modal; + }] + }; + + return $modalProvider; + }); + +angular.module('ui.bootstrap.pagination', []) + +.controller('PaginationController', ['$scope', '$attrs', '$parse', '$interpolate', function ($scope, $attrs, $parse, $interpolate) { + var self = this, + setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; + + this.init = function(defaultItemsPerPage) { + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = defaultItemsPerPage; + } + }; + + this.noPrevious = function() { + return this.page === 1; + }; + this.noNext = function() { + return this.page === $scope.totalPages; + }; + + this.isActive = function(page) { + return this.page === page; + }; + + this.calculateTotalPages = function() { + var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + return Math.max(totalPages || 0, 1); + }; + + this.getAttributeValue = function(attribute, defaultValue, interpolate) { + return angular.isDefined(attribute) ? (interpolate ? $interpolate(attribute)($scope.$parent) : $scope.$parent.$eval(attribute)) : defaultValue; + }; + + this.render = function() { + this.page = parseInt($scope.page, 10) || 1; + if (this.page > 0 && this.page <= $scope.totalPages) { + $scope.pages = this.getPages(this.page, $scope.totalPages); + } + }; + + $scope.selectPage = function(page) { + if ( ! self.isActive(page) && page > 0 && page <= $scope.totalPages) { + $scope.page = page; + $scope.onSelectPage({ page: page }); + } + }; + + $scope.$watch('page', function() { + self.render(); + }); + + $scope.$watch('totalItems', function() { + $scope.totalPages = self.calculateTotalPages(); + }); + + $scope.$watch('totalPages', function(value) { + setNumPages($scope.$parent, value); // Readonly variable + + if ( self.page > value ) { + $scope.selectPage(value); + } else { + self.render(); + } + }); +}]) + +.constant('paginationConfig', { + itemsPerPage: 10, + boundaryLinks: false, + directionLinks: true, + firstText: 'First', + previousText: 'Previous', + nextText: 'Next', + lastText: 'Last', + rotate: true +}) + +.directive('pagination', ['$parse', 'paginationConfig', function($parse, config) { + return { + restrict: 'EA', + scope: { + page: '=', + totalItems: '=', + onSelectPage:' &' + }, + controller: 'PaginationController', + templateUrl: 'template/pagination/pagination.html', + replace: true, + link: function(scope, element, attrs, paginationCtrl) { + + // Setup configuration parameters + var maxSize, + boundaryLinks = paginationCtrl.getAttributeValue(attrs.boundaryLinks, config.boundaryLinks ), + directionLinks = paginationCtrl.getAttributeValue(attrs.directionLinks, config.directionLinks ), + firstText = paginationCtrl.getAttributeValue(attrs.firstText, config.firstText, true), + previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), + nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), + lastText = paginationCtrl.getAttributeValue(attrs.lastText, config.lastText, true), + rotate = paginationCtrl.getAttributeValue(attrs.rotate, config.rotate); + + paginationCtrl.init(config.itemsPerPage); + + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); + } + + // Create page object used in template + function makePage(number, text, isActive, isDisabled) { + return { + number: number, + text: text, + active: isActive, + disabled: isDisabled + }; + } + + paginationCtrl.getPages = function(currentPage, totalPages) { + var pages = []; + + // Default page limits + var startPage = 1, endPage = totalPages; + var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); + + // recompute if maxSize + if ( isMaxSized ) { + if ( rotate ) { + // Current page is displayed in the middle of the visible ones + startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); + endPage = startPage + maxSize - 1; + + // Adjust if limit is exceeded + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; + } + } else { + // Visible pages are paginated with maxSize + startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; + + // Adjust last page if limit is exceeded + endPage = Math.min(startPage + maxSize - 1, totalPages); + } + } + + // Add page number links + for (var number = startPage; number <= endPage; number++) { + var page = makePage(number, number, paginationCtrl.isActive(number), false); + pages.push(page); + } + + // Add links to move between page sets + if ( isMaxSized && ! rotate ) { + if ( startPage > 1 ) { + var previousPageSet = makePage(startPage - 1, '...', false, false); + pages.unshift(previousPageSet); + } + + if ( endPage < totalPages ) { + var nextPageSet = makePage(endPage + 1, '...', false, false); + pages.push(nextPageSet); + } + } + + // Add previous & next links + if (directionLinks) { + var previousPage = makePage(currentPage - 1, previousText, false, paginationCtrl.noPrevious()); + pages.unshift(previousPage); + + var nextPage = makePage(currentPage + 1, nextText, false, paginationCtrl.noNext()); + pages.push(nextPage); + } + + // Add first & last links + if (boundaryLinks) { + var firstPage = makePage(1, firstText, false, paginationCtrl.noPrevious()); + pages.unshift(firstPage); + + var lastPage = makePage(totalPages, lastText, false, paginationCtrl.noNext()); + pages.push(lastPage); + } + + return pages; + }; + } + }; +}]) + +.constant('pagerConfig', { + itemsPerPage: 10, + previousText: '« Previous', + nextText: 'Next »', + align: true +}) + +.directive('pager', ['pagerConfig', function(config) { + return { + restrict: 'EA', + scope: { + page: '=', + totalItems: '=', + onSelectPage:' &' + }, + controller: 'PaginationController', + templateUrl: 'template/pagination/pager.html', + replace: true, + link: function(scope, element, attrs, paginationCtrl) { + + // Setup configuration parameters + var previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), + nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), + align = paginationCtrl.getAttributeValue(attrs.align, config.align); + + paginationCtrl.init(config.itemsPerPage); + + // Create page object used in template + function makePage(number, text, isDisabled, isPrevious, isNext) { + return { + number: number, + text: text, + disabled: isDisabled, + previous: ( align && isPrevious ), + next: ( align && isNext ) + }; + } + + paginationCtrl.getPages = function(currentPage) { + return [ + makePage(currentPage - 1, previousText, paginationCtrl.noPrevious(), true, false), + makePage(currentPage + 1, nextText, paginationCtrl.noNext(), false, true) + ]; + }; + } + }; +}]); + +/** + * The following features are still outstanding: animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html tooltips, and selector delegation. + */ +angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) + +/** + * The $tooltip service creates tooltip- and popover-like directives as well as + * houses global options for them. + */ +.provider( '$tooltip', function () { + // The default options tooltip and popover. + var defaultOptions = { + placement: 'top', + animation: true, + popupDelay: 0 + }; + + // Default hide triggers for each show trigger + var triggerMap = { + 'mouseenter': 'mouseleave', + 'click': 'click', + 'focus': 'blur' + }; + + // The options specified to the provider globally. + var globalOptions = {}; + + /** + * `options({})` allows global configuration of all tooltips in the + * application. + * + * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) { + * // place tooltips left instead of top by default + * $tooltipProvider.options( { placement: 'left' } ); + * }); + */ + this.options = function( value ) { + angular.extend( globalOptions, value ); + }; + + /** + * This allows you to extend the set of trigger mappings available. E.g.: + * + * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' ); + */ + this.setTriggers = function setTriggers ( triggers ) { + angular.extend( triggerMap, triggers ); + }; + + /** + * This is a helper function for translating camel-case to snake-case. + */ + function snake_case(name){ + var regexp = /[A-Z]/g; + var separator = '-'; + return name.replace(regexp, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); + } + + /** + * Returns the actual instance of the $tooltip service. + * TODO support multiple triggers + */ + this.$get = [ '$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $parse, $document, $position, $interpolate ) { + return function $tooltip ( type, prefix, defaultTriggerShow ) { + var options = angular.extend( {}, defaultOptions, globalOptions ); + + /** + * Returns an object of show and hide triggers. + * + * If a trigger is supplied, + * it is used to show the tooltip; otherwise, it will use the `trigger` + * option passed to the `$tooltipProvider.options` method; else it will + * default to the trigger supplied to this directive factory. + * + * The hide trigger is based on the show trigger. If the `trigger` option + * was passed to the `$tooltipProvider.options` method, it will use the + * mapped trigger from `triggerMap` or the passed trigger if the map is + * undefined; otherwise, it uses the `triggerMap` value of the show + * trigger; else it will just use the show trigger. + */ + function getTriggers ( trigger ) { + var show = trigger || options.trigger || defaultTriggerShow; + var hide = triggerMap[show] || show; + return { + show: show, + hide: hide + }; + } + + var directiveName = snake_case( type ); + + var startSym = $interpolate.startSymbol(); + var endSym = $interpolate.endSymbol(); + var template = + '
      '+ + '
      '; + + return { + restrict: 'EA', + scope: true, + compile: function (tElem, tAttrs) { + var tooltipLinker = $compile( template ); + + return function link ( scope, element, attrs ) { + var tooltip; + var transitionTimeout; + var popupTimeout; + var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false; + var triggers = getTriggers( undefined ); + var hasRegisteredTriggers = false; + var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']); + + var positionTooltip = function (){ + var position, + ttWidth, + ttHeight, + ttPosition; + // Get the position of the directive element. + position = appendToBody ? $position.offset( element ) : $position.position( element ); + + // Get the height and width of the tooltip so we can center it. + ttWidth = tooltip.prop( 'offsetWidth' ); + ttHeight = tooltip.prop( 'offsetHeight' ); + + // Calculate the tooltip's top and left coordinates to center it with + // this directive. + switch ( scope.tt_placement ) { + case 'right': + ttPosition = { + top: position.top + position.height / 2 - ttHeight / 2, + left: position.left + position.width + }; + break; + case 'bottom': + ttPosition = { + top: position.top + position.height, + left: position.left + position.width / 2 - ttWidth / 2 + }; + break; + case 'left': + ttPosition = { + top: position.top + position.height / 2 - ttHeight / 2, + left: position.left - ttWidth + }; + break; + default: + ttPosition = { + top: position.top - ttHeight, + left: position.left + position.width / 2 - ttWidth / 2 + }; + break; + } + + ttPosition.top += 'px'; + ttPosition.left += 'px'; + + // Now set the calculated positioning. + tooltip.css( ttPosition ); + + }; + + // By default, the tooltip is not open. + // TODO add ability to start tooltip opened + scope.tt_isOpen = false; + + function toggleTooltipBind () { + if ( ! scope.tt_isOpen ) { + showTooltipBind(); + } else { + hideTooltipBind(); + } + } + + // Show the tooltip with delay if specified, otherwise show it immediately + function showTooltipBind() { + if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) { + return; + } + if ( scope.tt_popupDelay ) { + popupTimeout = $timeout( show, scope.tt_popupDelay, false ); + popupTimeout.then(function(reposition){reposition();}); + } else { + show()(); + } + } + + function hideTooltipBind () { + scope.$apply(function () { + hide(); + }); + } + + // Show the tooltip popup element. + function show() { + + + // Don't show empty tooltips. + if ( ! scope.tt_content ) { + return angular.noop; + } + + createTooltip(); + + // If there is a pending remove transition, we must cancel it, lest the + // tooltip be mysteriously removed. + if ( transitionTimeout ) { + $timeout.cancel( transitionTimeout ); + } + + // Set the initial positioning. + tooltip.css({ top: 0, left: 0, display: 'block' }); + + // Now we add it to the DOM because need some info about it. But it's not + // visible yet anyway. + if ( appendToBody ) { + $document.find( 'body' ).append( tooltip ); + } else { + element.after( tooltip ); + } + + positionTooltip(); + + // And show the tooltip. + scope.tt_isOpen = true; + scope.$digest(); // digest required as $apply is not called + + // Return positioning function as promise callback for correct + // positioning after draw. + return positionTooltip; + } + + // Hide the tooltip popup element. + function hide() { + // First things first: we don't show it anymore. + scope.tt_isOpen = false; + + //if tooltip is going to be shown after delay, we must cancel this + $timeout.cancel( popupTimeout ); + + // And now we remove it from the DOM. However, if we have animation, we + // need to wait for it to expire beforehand. + // FIXME: this is a placeholder for a port of the transitions library. + if ( scope.tt_animation ) { + transitionTimeout = $timeout(removeTooltip, 500); + } else { + removeTooltip(); + } + } + + function createTooltip() { + // There can only be one tooltip element per directive shown at once. + if (tooltip) { + removeTooltip(); + } + tooltip = tooltipLinker(scope, function () {}); + + // Get contents rendered into the tooltip + scope.$digest(); + } + + function removeTooltip() { + if (tooltip) { + tooltip.remove(); + tooltip = null; + } + } + + /** + * Observe the relevant attributes. + */ + attrs.$observe( type, function ( val ) { + scope.tt_content = val; + + if (!val && scope.tt_isOpen ) { + hide(); + } + }); + + attrs.$observe( prefix+'Title', function ( val ) { + scope.tt_title = val; + }); + + attrs.$observe( prefix+'Placement', function ( val ) { + scope.tt_placement = angular.isDefined( val ) ? val : options.placement; + }); + + attrs.$observe( prefix+'PopupDelay', function ( val ) { + var delay = parseInt( val, 10 ); + scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay; + }); + + var unregisterTriggers = function() { + if (hasRegisteredTriggers) { + element.unbind( triggers.show, showTooltipBind ); + element.unbind( triggers.hide, hideTooltipBind ); + } + }; + + attrs.$observe( prefix+'Trigger', function ( val ) { + unregisterTriggers(); + + triggers = getTriggers( val ); + + if ( triggers.show === triggers.hide ) { + element.bind( triggers.show, toggleTooltipBind ); + } else { + element.bind( triggers.show, showTooltipBind ); + element.bind( triggers.hide, hideTooltipBind ); + } + + hasRegisteredTriggers = true; + }); + + var animation = scope.$eval(attrs[prefix + 'Animation']); + scope.tt_animation = angular.isDefined(animation) ? !!animation : options.animation; + + attrs.$observe( prefix+'AppendToBody', function ( val ) { + appendToBody = angular.isDefined( val ) ? $parse( val )( scope ) : appendToBody; + }); + + // if a tooltip is attached to we need to remove it on + // location change as its parent scope will probably not be destroyed + // by the change. + if ( appendToBody ) { + scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () { + if ( scope.tt_isOpen ) { + hide(); + } + }); + } + + // Make sure tooltip is destroyed and removed. + scope.$on('$destroy', function onDestroyTooltip() { + $timeout.cancel( transitionTimeout ); + $timeout.cancel( popupTimeout ); + unregisterTriggers(); + removeTooltip(); + }); + }; + } + }; + }; + }]; +}) + +.directive( 'tooltipPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-popup.html' + }; +}) + +.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltip', 'tooltip', 'mouseenter' ); +}]) + +.directive( 'tooltipHtmlUnsafePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html' + }; +}) + +.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' ); +}]); + +/** + * The following features are still outstanding: popup delay, animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html popovers, and selector delegatation. + */ +angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] ) + +.directive( 'popoverPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/popover/popover.html' + }; +}) + +.directive( 'popover', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'popover', 'popover', 'click' ); +}]); + +angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition']) + +.constant('progressConfig', { + animate: true, + max: 100 +}) + +.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', '$transition', function($scope, $attrs, progressConfig, $transition) { + var self = this, + bars = [], + max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max, + animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; + + this.addBar = function(bar, element) { + var oldValue = 0, index = bar.$parent.$index; + if ( angular.isDefined(index) && bars[index] ) { + oldValue = bars[index].value; + } + bars.push(bar); + + this.update(element, bar.value, oldValue); + + bar.$watch('value', function(value, oldValue) { + if (value !== oldValue) { + self.update(element, value, oldValue); + } + }); + + bar.$on('$destroy', function() { + self.removeBar(bar); + }); + }; + + // Update bar element width + this.update = function(element, newValue, oldValue) { + var percent = this.getPercentage(newValue); + + if (animate) { + element.css('width', this.getPercentage(oldValue) + '%'); + $transition(element, {width: percent + '%'}); + } else { + element.css({'transition': 'none', 'width': percent + '%'}); + } + }; + + this.removeBar = function(bar) { + bars.splice(bars.indexOf(bar), 1); + }; + + this.getPercentage = function(value) { + return Math.round(100 * value / max); + }; +}]) + +.directive('progress', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + require: 'progress', + scope: {}, + template: '
      ' + //templateUrl: 'template/progressbar/progress.html' // Works in AngularJS 1.2 + }; +}) + +.directive('bar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + require: '^progress', + scope: { + value: '=', + type: '@' + }, + templateUrl: 'template/progressbar/bar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, element); + } + }; +}) + +.directive('progressbar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + scope: { + value: '=', + type: '@' + }, + templateUrl: 'template/progressbar/progressbar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, angular.element(element.children()[0])); + } + }; +}); +angular.module('ui.bootstrap.rating', []) + +.constant('ratingConfig', { + max: 5, + stateOn: null, + stateOff: null +}) + +.controller('RatingController', ['$scope', '$attrs', '$parse', 'ratingConfig', function($scope, $attrs, $parse, ratingConfig) { + + this.maxRange = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max; + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; + + this.createRateObjects = function(states) { + var defaultOptions = { + stateOn: this.stateOn, + stateOff: this.stateOff + }; + + for (var i = 0, n = states.length; i < n; i++) { + states[i] = angular.extend({ index: i }, defaultOptions, states[i]); + } + return states; + }; + + // Get objects used in template + $scope.range = angular.isDefined($attrs.ratingStates) ? this.createRateObjects(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createRateObjects(new Array(this.maxRange)); + + $scope.rate = function(value) { + if ( $scope.value !== value && !$scope.readonly ) { + $scope.value = value; + } + }; + + $scope.enter = function(value) { + if ( ! $scope.readonly ) { + $scope.val = value; + } + $scope.onHover({value: value}); + }; + + $scope.reset = function() { + $scope.val = angular.copy($scope.value); + $scope.onLeave(); + }; + + $scope.$watch('value', function(value) { + $scope.val = value; + }); + + $scope.readonly = false; + if ($attrs.readonly) { + $scope.$parent.$watch($parse($attrs.readonly), function(value) { + $scope.readonly = !!value; + }); + } +}]) + +.directive('rating', function() { + return { + restrict: 'EA', + scope: { + value: '=', + onHover: '&', + onLeave: '&' + }, + controller: 'RatingController', + templateUrl: 'template/rating/rating.html', + replace: true + }; +}); + +/** + * @ngdoc overview + * @name ui.bootstrap.tabs + * + * @description + * AngularJS version of the tabs directive. + */ + +angular.module('ui.bootstrap.tabs', []) + +.controller('TabsetController', ['$scope', function TabsetCtrl($scope) { + var ctrl = this, + tabs = ctrl.tabs = $scope.tabs = []; + + ctrl.select = function(tab) { + angular.forEach(tabs, function(tab) { + tab.active = false; + }); + tab.active = true; + }; + + ctrl.addTab = function addTab(tab) { + tabs.push(tab); + if (tabs.length === 1 || tab.active) { + ctrl.select(tab); + } + }; + + ctrl.removeTab = function removeTab(tab) { + var index = tabs.indexOf(tab); + //Select a new tab if the tab to be removed is selected + if (tab.active && tabs.length > 1) { + //If this is the last tab, select the previous tab. else, the next tab. + var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; + ctrl.select(tabs[newActiveIndex]); + } + tabs.splice(index, 1); + }; +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabset + * @restrict EA + * + * @description + * Tabset is the outer container for the tabs directive + * + * @param {boolean=} vertical Whether or not to use vertical styling for the tabs. + * @param {boolean=} justified Whether or not to use justified styling for the tabs. + * + * @example + + + + First Content! + Second Content! + +
      + + First Vertical Content! + Second Vertical Content! + + + First Justified Content! + Second Justified Content! + +
      +
      + */ +.directive('tabset', function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + scope: {}, + controller: 'TabsetController', + templateUrl: 'template/tabs/tabset.html', + link: function(scope, element, attrs) { + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; + scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; + scope.type = angular.isDefined(attrs.type) ? scope.$parent.$eval(attrs.type) : 'tabs'; + } + }; +}) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tab + * @restrict EA + * + * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}. + * @param {string=} select An expression to evaluate when the tab is selected. + * @param {boolean=} active A binding, telling whether or not this tab is selected. + * @param {boolean=} disabled A binding, telling whether or not this tab is disabled. + * + * @description + * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}. + * + * @example + + +
      + + +
      + + First Tab + + Alert me! + Second Tab, with alert callback and html heading! + + + {{item.content}} + + +
      +
      + + function TabsDemoCtrl($scope) { + $scope.items = [ + { title:"Dynamic Title 1", content:"Dynamic Item 0" }, + { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true } + ]; + + $scope.alertMe = function() { + setTimeout(function() { + alert("You've selected the alert tab!"); + }); + }; + }; + +
      + */ + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabHeading + * @restrict EA + * + * @description + * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element. + * + * @example + + + + + HTML in my titles?! + And some content, too! + + + Icon heading?!? + That's right. + + + + + */ +.directive('tab', ['$parse', function($parse) { + return { + require: '^tabset', + restrict: 'EA', + replace: true, + templateUrl: 'template/tabs/tab.html', + transclude: true, + scope: { + heading: '@', + onSelect: '&select', //This callback is called in contentHeadingTransclude + //once it inserts the tab's content into the dom + onDeselect: '&deselect' + }, + controller: function() { + //Empty controller so other directives can require being 'under' a tab + }, + compile: function(elm, attrs, transclude) { + return function postLink(scope, elm, attrs, tabsetCtrl) { + var getActive, setActive; + if (attrs.active) { + getActive = $parse(attrs.active); + setActive = getActive.assign; + scope.$parent.$watch(getActive, function updateActive(value, oldVal) { + // Avoid re-initializing scope.active as it is already initialized + // below. (watcher is called async during init with value === + // oldVal) + if (value !== oldVal) { + scope.active = !!value; + } + }); + scope.active = getActive(scope.$parent); + } else { + setActive = getActive = angular.noop; + } + + scope.$watch('active', function(active) { + // Note this watcher also initializes and assigns scope.active to the + // attrs.active expression. + setActive(scope.$parent, active); + if (active) { + tabsetCtrl.select(scope); + scope.onSelect(); + } else { + scope.onDeselect(); + } + }); + + scope.disabled = false; + if ( attrs.disabled ) { + scope.$parent.$watch($parse(attrs.disabled), function(value) { + scope.disabled = !! value; + }); + } + + scope.select = function() { + if ( ! scope.disabled ) { + scope.active = true; + } + }; + + tabsetCtrl.addTab(scope); + scope.$on('$destroy', function() { + tabsetCtrl.removeTab(scope); + }); + + + //We need to transclude later, once the content container is ready. + //when this link happens, we're inside a tab heading. + scope.$transcludeFn = transclude; + }; + } + }; +}]) + +.directive('tabHeadingTransclude', [function() { + return { + restrict: 'A', + require: '^tab', + link: function(scope, elm, attrs, tabCtrl) { + scope.$watch('headingElement', function updateHeadingElement(heading) { + if (heading) { + elm.html(''); + elm.append(heading); + } + }); + } + }; +}]) + +.directive('tabContentTransclude', function() { + return { + restrict: 'A', + require: '^tabset', + link: function(scope, elm, attrs) { + var tab = scope.$eval(attrs.tabContentTransclude); + + //Now our tab is ready to be transcluded: both the tab heading area + //and the tab content area are loaded. Transclude 'em both. + tab.$transcludeFn(tab.$parent, function(contents) { + angular.forEach(contents, function(node) { + if (isTabHeading(node)) { + //Let tabHeadingTransclude know. + tab.headingElement = node; + } else { + elm.append(node); + } + }); + }); + } + }; + function isTabHeading(node) { + return node.tagName && ( + node.hasAttribute('tab-heading') || + node.hasAttribute('data-tab-heading') || + node.tagName.toLowerCase() === 'tab-heading' || + node.tagName.toLowerCase() === 'data-tab-heading' + ); + } +}) + +; + +angular.module('ui.bootstrap.timepicker', []) + +.constant('timepickerConfig', { + hourStep: 1, + minuteStep: 1, + showMeridian: true, + meridians: null, + readonlyInput: false, + mousewheel: true +}) + +.directive('timepicker', ['$parse', '$log', 'timepickerConfig', '$locale', function ($parse, $log, timepickerConfig, $locale) { + return { + restrict: 'EA', + require:'?^ngModel', + replace: true, + scope: {}, + templateUrl: 'template/timepicker/timepicker.html', + link: function(scope, element, attrs, ngModel) { + if ( !ngModel ) { + return; // do nothing if no ng-model + } + + var selected = new Date(), + meridians = angular.isDefined(attrs.meridians) ? scope.$parent.$eval(attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; + + var hourStep = timepickerConfig.hourStep; + if (attrs.hourStep) { + scope.$parent.$watch($parse(attrs.hourStep), function(value) { + hourStep = parseInt(value, 10); + }); + } + + var minuteStep = timepickerConfig.minuteStep; + if (attrs.minuteStep) { + scope.$parent.$watch($parse(attrs.minuteStep), function(value) { + minuteStep = parseInt(value, 10); + }); + } + + // 12H / 24H mode + scope.showMeridian = timepickerConfig.showMeridian; + if (attrs.showMeridian) { + scope.$parent.$watch($parse(attrs.showMeridian), function(value) { + scope.showMeridian = !!value; + + if ( ngModel.$error.time ) { + // Evaluate from template + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined( hours ) && angular.isDefined( minutes )) { + selected.setHours( hours ); + refresh(); + } + } else { + updateTemplate(); + } + }); + } + + // Get scope.hours in 24H mode if valid + function getHoursFromTemplate ( ) { + var hours = parseInt( scope.hours, 10 ); + var valid = ( scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24); + if ( !valid ) { + return undefined; + } + + if ( scope.showMeridian ) { + if ( hours === 12 ) { + hours = 0; + } + if ( scope.meridian === meridians[1] ) { + hours = hours + 12; + } + } + return hours; + } + + function getMinutesFromTemplate() { + var minutes = parseInt(scope.minutes, 10); + return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined; + } + + function pad( value ) { + return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value; + } + + // Input elements + var inputs = element.find('input'), hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); + + // Respond on mousewheel spin + var mousewheel = (angular.isDefined(attrs.mousewheel)) ? scope.$eval(attrs.mousewheel) : timepickerConfig.mousewheel; + if ( mousewheel ) { + + var isScrollingUp = function(e) { + if (e.originalEvent) { + e = e.originalEvent; + } + //pick correct delta variable depending on event + var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY; + return (e.detail || delta > 0); + }; + + hoursInputEl.bind('mousewheel wheel', function(e) { + scope.$apply( (isScrollingUp(e)) ? scope.incrementHours() : scope.decrementHours() ); + e.preventDefault(); + }); + + minutesInputEl.bind('mousewheel wheel', function(e) { + scope.$apply( (isScrollingUp(e)) ? scope.incrementMinutes() : scope.decrementMinutes() ); + e.preventDefault(); + }); + } + + scope.readonlyInput = (angular.isDefined(attrs.readonlyInput)) ? scope.$eval(attrs.readonlyInput) : timepickerConfig.readonlyInput; + if ( ! scope.readonlyInput ) { + + var invalidate = function(invalidHours, invalidMinutes) { + ngModel.$setViewValue( null ); + ngModel.$setValidity('time', false); + if (angular.isDefined(invalidHours)) { + scope.invalidHours = invalidHours; + } + if (angular.isDefined(invalidMinutes)) { + scope.invalidMinutes = invalidMinutes; + } + }; + + scope.updateHours = function() { + var hours = getHoursFromTemplate(); + + if ( angular.isDefined(hours) ) { + selected.setHours( hours ); + refresh( 'h' ); + } else { + invalidate(true); + } + }; + + hoursInputEl.bind('blur', function(e) { + if ( !scope.validHours && scope.hours < 10) { + scope.$apply( function() { + scope.hours = pad( scope.hours ); + }); + } + }); + + scope.updateMinutes = function() { + var minutes = getMinutesFromTemplate(); + + if ( angular.isDefined(minutes) ) { + selected.setMinutes( minutes ); + refresh( 'm' ); + } else { + invalidate(undefined, true); + } + }; + + minutesInputEl.bind('blur', function(e) { + if ( !scope.invalidMinutes && scope.minutes < 10 ) { + scope.$apply( function() { + scope.minutes = pad( scope.minutes ); + }); + } + }); + } else { + scope.updateHours = angular.noop; + scope.updateMinutes = angular.noop; + } + + ngModel.$render = function() { + var date = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : null; + + if ( isNaN(date) ) { + ngModel.$setValidity('time', false); + $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else { + if ( date ) { + selected = date; + } + makeValid(); + updateTemplate(); + } + }; + + // Call internally when we know that model is valid. + function refresh( keyboardChange ) { + makeValid(); + ngModel.$setViewValue( new Date(selected) ); + updateTemplate( keyboardChange ); + } + + function makeValid() { + ngModel.$setValidity('time', true); + scope.invalidHours = false; + scope.invalidMinutes = false; + } + + function updateTemplate( keyboardChange ) { + var hours = selected.getHours(), minutes = selected.getMinutes(); + + if ( scope.showMeridian ) { + hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system + } + scope.hours = keyboardChange === 'h' ? hours : pad(hours); + scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes); + scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; + } + + function addMinutes( minutes ) { + var dt = new Date( selected.getTime() + minutes * 60000 ); + selected.setHours( dt.getHours(), dt.getMinutes() ); + refresh(); + } + + scope.incrementHours = function() { + addMinutes( hourStep * 60 ); + }; + scope.decrementHours = function() { + addMinutes( - hourStep * 60 ); + }; + scope.incrementMinutes = function() { + addMinutes( minuteStep ); + }; + scope.decrementMinutes = function() { + addMinutes( - minuteStep ); + }; + scope.toggleMeridian = function() { + addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) ); + }; + } + }; +}]); + +angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml']) + +/** + * A helper service that can parse typeahead's syntax (string provided by users) + * Extracted to a separate service for ease of unit testing + */ + .factory('typeaheadParser', ['$parse', function ($parse) { + + // 00000111000000000000022200000000000000003333333333333330000000000044000 + var TYPEAHEAD_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/; + + return { + parse:function (input) { + + var match = input.match(TYPEAHEAD_REGEXP), modelMapper, viewMapper, source; + if (!match) { + throw new Error( + "Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_'" + + " but got '" + input + "'."); + } + + return { + itemName:match[3], + source:$parse(match[4]), + viewMapper:$parse(match[2] || match[1]), + modelMapper:$parse(match[1]) + }; + } + }; +}]) + + .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', + function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { + + var HOT_KEYS = [9, 13, 27, 38, 40]; + + return { + require:'ngModel', + link:function (originalScope, element, attrs, modelCtrl) { + + //SUPPORTED ATTRIBUTES (OPTIONS) + + //minimal no of characters that needs to be entered before typeahead kicks-in + var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1; + + //minimal wait time after last character typed before typehead kicks-in + var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; + + //should it restrict model values to the ones selected from the popup only? + var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; + + //binding to a variable that indicates if matches are being retrieved asynchronously + var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; + + //a callback executed when a match is selected + var onSelectCallback = $parse(attrs.typeaheadOnSelect); + + var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; + + var appendToBody = attrs.typeaheadAppendToBody ? $parse(attrs.typeaheadAppendToBody) : false; + + //INTERNAL VARIABLES + + //model setter executed upon match selection + var $setModelValue = $parse(attrs.ngModel).assign; + + //expressions used by typeahead + var parserResult = typeaheadParser.parse(attrs.typeahead); + + var hasFocus; + + //pop-up element used to display matches + var popUpEl = angular.element('
      '); + popUpEl.attr({ + matches: 'matches', + active: 'activeIdx', + select: 'select(activeIdx)', + query: 'query', + position: 'position' + }); + //custom item template + if (angular.isDefined(attrs.typeaheadTemplateUrl)) { + popUpEl.attr('template-url', attrs.typeaheadTemplateUrl); + } + + //create a child scope for the typeahead directive so we are not polluting original scope + //with typeahead-specific data (matches, query etc.) + var scope = originalScope.$new(); + originalScope.$on('$destroy', function(){ + scope.$destroy(); + }); + + var resetMatches = function() { + scope.matches = []; + scope.activeIdx = -1; + }; + + var getMatchesAsync = function(inputValue) { + + var locals = {$viewValue: inputValue}; + isLoadingSetter(originalScope, true); + $q.when(parserResult.source(originalScope, locals)).then(function(matches) { + + //it might happen that several async queries were in progress if a user were typing fast + //but we are interested only in responses that correspond to the current view value + if (inputValue === modelCtrl.$viewValue && hasFocus) { + if (matches.length > 0) { + + scope.activeIdx = 0; + scope.matches.length = 0; + + //transform labels + for(var i=0; i= minSearch) { + if (waitTime > 0) { + if (timeoutPromise) { + $timeout.cancel(timeoutPromise);//cancel previous timeout + } + timeoutPromise = $timeout(function () { + getMatchesAsync(inputValue); + }, waitTime); + } else { + getMatchesAsync(inputValue); + } + } else { + isLoadingSetter(originalScope, false); + resetMatches(); + } + + if (isEditable) { + return inputValue; + } else { + if (!inputValue) { + // Reset in case user had typed something previously. + modelCtrl.$setValidity('editable', true); + return inputValue; + } else { + modelCtrl.$setValidity('editable', false); + return undefined; + } + } + }); + + modelCtrl.$formatters.push(function (modelValue) { + + var candidateViewValue, emptyViewValue; + var locals = {}; + + if (inputFormatter) { + + locals['$model'] = modelValue; + return inputFormatter(originalScope, locals); + + } else { + + //it might happen that we don't have enough info to properly render input value + //we need to check for this situation and simply return model value if we can't apply custom formatting + locals[parserResult.itemName] = modelValue; + candidateViewValue = parserResult.viewMapper(originalScope, locals); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); + + return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; + } + }); + + scope.select = function (activeIdx) { + //called from within the $digest() cycle + var locals = {}; + var model, item; + + locals[parserResult.itemName] = item = scope.matches[activeIdx].model; + model = parserResult.modelMapper(originalScope, locals); + $setModelValue(originalScope, model); + modelCtrl.$setValidity('editable', true); + + onSelectCallback(originalScope, { + $item: item, + $model: model, + $label: parserResult.viewMapper(originalScope, locals) + }); + + resetMatches(); + + //return focus to the input element if a mach was selected via a mouse click event + element[0].focus(); + }; + + //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27) + element.bind('keydown', function (evt) { + + //typeahead is open and an "interesting" key was pressed + if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { + return; + } + + evt.preventDefault(); + + if (evt.which === 40) { + scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; + scope.$digest(); + + } else if (evt.which === 38) { + scope.activeIdx = (scope.activeIdx ? scope.activeIdx : scope.matches.length) - 1; + scope.$digest(); + + } else if (evt.which === 13 || evt.which === 9) { + scope.$apply(function () { + scope.select(scope.activeIdx); + }); + + } else if (evt.which === 27) { + evt.stopPropagation(); + + resetMatches(); + scope.$digest(); + } + }); + + element.bind('blur', function (evt) { + hasFocus = false; + }); + + // Keep reference to click handler to unbind it. + var dismissClickHandler = function (evt) { + if (element[0] !== evt.target) { + resetMatches(); + scope.$digest(); + } + }; + + $document.bind('click', dismissClickHandler); + + originalScope.$on('$destroy', function(){ + $document.unbind('click', dismissClickHandler); + }); + + var $popup = $compile(popUpEl)(scope); + if ( appendToBody ) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + } + }; + +}]) + + .directive('typeaheadPopup', function () { + return { + restrict:'EA', + scope:{ + matches:'=', + query:'=', + active:'=', + position:'=', + select:'&' + }, + replace:true, + templateUrl:'template/typeahead/typeahead-popup.html', + link:function (scope, element, attrs) { + + scope.templateUrl = attrs.templateUrl; + + scope.isOpen = function () { + return scope.matches.length > 0; + }; + + scope.isActive = function (matchIdx) { + return scope.active == matchIdx; + }; + + scope.selectActive = function (matchIdx) { + scope.active = matchIdx; + }; + + scope.selectMatch = function (activeIdx) { + scope.select({activeIdx:activeIdx}); + }; + } + }; + }) + + .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) { + return { + restrict:'EA', + scope:{ + index:'=', + match:'=', + query:'=' + }, + link:function (scope, element, attrs) { + var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html'; + $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){ + element.replaceWith($compile(tplContent.trim())(scope)); + }); + } + }; + }]) + + .filter('typeaheadHighlight', function() { + + function escapeRegexp(queryToEscape) { + return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); + } + + return function(matchItem, query) { + return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; + }; + }); \ No newline at end of file diff --git a/dist/bower_components/angular-bootstrap/ui-bootstrap.min.js b/dist/bower_components/angular-bootstrap/ui-bootstrap.min.js new file mode 100644 index 000000000..08ee33ad1 --- /dev/null +++ b/dist/bower_components/angular-bootstrap/ui-bootstrap.min.js @@ -0,0 +1,9 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.10.0 - 2014-01-13 + * License: MIT + */ +angular.module("ui.bootstrap",["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0)}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){if(k)k=!1,i(),c.css({height:0});else{c.css({height:c[0].scrollHeight+"px"});{c[0].offsetWidth}c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i)}}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(this.groups.indexOf(a),1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",["$parse",function(a){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(b,c,d,e){var f,g;e.addGroup(b),b.isOpen=!1,d.isOpen&&(f=a(d.isOpen),g=f.assign,b.$parent.$watch(f,function(a){b.isOpen=!!a})),b.$watch("isOpen",function(a){a&&e.closeOthers(b),g&&g(b.$parent,a)})}}}]).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",compile:function(a,b,c){return function(a,b,d,e){e.setHeading(c(a,function(){}))}}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"=",close:"&"}}}),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){b.hasClass(e.activeClass)||a.$apply(function(){f.$setViewValue(a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$transition","$q",function(a,b,c){function d(){e();var c=+a.interval;!isNaN(c)&&c>=0&&(g=b(f,c))}function e(){g&&(b.cancel(g),g=null)}function f(){h?(a.next(),d()):a.pause()}var g,h,i=this,j=i.slides=[],k=-1;i.currentSlide=null;var l=!1;i.select=function(e,f){function g(){if(!l){if(i.currentSlide&&angular.isString(f)&&!a.noTransition&&e.$element){e.$element.addClass(f);{e.$element[0].offsetWidth}angular.forEach(j,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(e,{direction:f,active:!0,entering:!0}),angular.extend(i.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=c(e.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(e,i.currentSlide)}else h(e,i.currentSlide);i.currentSlide=e,k=m,d()}}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var m=j.indexOf(e);void 0===f&&(f=m>k?"next":"prev"),e&&e!==i.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){l=!0}),i.indexOfSlide=function(a){return j.indexOf(a)},a.next=function(){var b=(k+1)%j.length;return a.$currentTransition?void 0:i.select(j[b],"next")},a.prev=function(){var b=0>k-1?j.length-1:k-1;return a.$currentTransition?void 0:i.select(j[b],"prev")},a.select=function(a){i.select(a)},a.isActive=function(a){return i.currentSlide===a},a.slides=function(){return j},a.$watch("interval",d),a.$on("$destroy",e),a.play=function(){h||(h=!0,d())},a.pause=function(){a.noPause||(h=!1,e())},i.addSlide=function(b,c){b.$element=c,j.push(b),1===j.length||b.active?(i.select(j[j.length-1]),1==j.length&&a.play()):b.active=!1},i.removeSlide=function(a){var b=j.indexOf(a);j.splice(b,1),j.length>0&&a.active?b>=j.length?i.select(j[b-1]):i.select(j[b]):k>b&&k--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",["$parse",function(a){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{},link:function(b,c,d,e){if(d.active){var f=a(d.active),g=f.assign,h=b.active=f(b.$parent);b.$watch(function(){var a=f(b.$parent);return a!==b.active&&(a!==h?h=b.active=a:g(b.$parent,a=h=b.active)),a})}e.addSlide(b,c),b.$on("$destroy",function(){e.removeSlide(b)}),b.$watch("active",function(a){a&&e.select(b)})}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].body.scrollTop||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].body.scrollLeft||a[0].documentElement.scrollLeft)}}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.position"]).constant("datepickerConfig",{dayFormat:"dd",monthFormat:"MMMM",yearFormat:"yyyy",dayHeaderFormat:"EEE",dayTitleFormat:"MMMM yyyy",monthTitleFormat:"yyyy",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","dateFilter","datepickerConfig",function(a,b,c,d){function e(b,c){return angular.isDefined(b)?a.$parent.$eval(b):c}function f(a,b){return new Date(a,b,0).getDate()}function g(a,b){for(var c=new Array(b),d=a,e=0;b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a,b,d,e){return{date:a,label:c(a,b),selected:!!d,secondary:!!e}}var i={day:e(b.dayFormat,d.dayFormat),month:e(b.monthFormat,d.monthFormat),year:e(b.yearFormat,d.yearFormat),dayHeader:e(b.dayHeaderFormat,d.dayHeaderFormat),dayTitle:e(b.dayTitleFormat,d.dayTitleFormat),monthTitle:e(b.monthTitleFormat,d.monthTitleFormat)},j=e(b.startingDay,d.startingDay),k=e(b.yearRange,d.yearRange);this.minDate=d.minDate?new Date(d.minDate):null,this.maxDate=d.maxDate?new Date(d.maxDate):null,this.modes=[{name:"day",getVisibleDates:function(a,b){var d=a.getFullYear(),e=a.getMonth(),k=new Date(d,e,1),l=j-k.getDay(),m=l>0?7-l:-l,n=new Date(k),o=0;m>0&&(n.setDate(-m+1),o+=m),o+=f(d,e+1),o+=(7-o%7)%7;for(var p=g(n,o),q=new Array(7),r=0;o>r;r++){var s=new Date(p[r]);p[r]=h(s,i.day,b&&b.getDate()===s.getDate()&&b.getMonth()===s.getMonth()&&b.getFullYear()===s.getFullYear(),s.getMonth()!==e)}for(var t=0;7>t;t++)q[t]=c(p[t].date,i.dayHeader);return{objects:p,title:c(a,i.dayTitle),labels:q}},compare:function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},split:7,step:{months:1}},{name:"month",getVisibleDates:function(a,b){for(var d=new Array(12),e=a.getFullYear(),f=0;12>f;f++){var g=new Date(e,f,1);d[f]=h(g,i.month,b&&b.getMonth()===f&&b.getFullYear()===e)}return{objects:d,title:c(a,i.monthTitle)}},compare:function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},split:3,step:{years:1}},{name:"year",getVisibleDates:function(a,b){for(var c=new Array(k),d=a.getFullYear(),e=parseInt((d-1)/k,10)*k+1,f=0;k>f;f++){var g=new Date(e+f,0,1);c[f]=h(g,i.year,b&&b.getFullYear()===g.getFullYear())}return{objects:c,title:[c[0].label,c[k-1].label].join(" - ")}},compare:function(a,b){return a.getFullYear()-b.getFullYear()},split:5,step:{years:k}}],this.isDisabled=function(b,c){var d=this.modes[c||0];return this.minDate&&d.compare(b,this.minDate)<0||this.maxDate&&d.compare(b,this.maxDate)>0||a.dateDisabled&&a.dateDisabled({date:b,mode:d.name})}}]).directive("datepicker",["dateFilter","$parse","datepickerConfig","$log",function(a,b,c,d){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,e,f,g){function h(){a.showWeekNumbers=0===o&&q}function i(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c}function j(b){var c=null,e=!0;n.$modelValue&&(c=new Date(n.$modelValue),isNaN(c)?(e=!1,d.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):b&&(p=c)),n.$setValidity("date",e);var f=m.modes[o],g=f.getVisibleDates(p,c);angular.forEach(g.objects,function(a){a.disabled=m.isDisabled(a.date,o)}),n.$setValidity("date-disabled",!c||!m.isDisabled(c)),a.rows=i(g.objects,f.split),a.labels=g.labels||[],a.title=g.title}function k(a){o=a,h(),j()}function l(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var m=g[0],n=g[1];if(n){var o=0,p=new Date,q=c.showWeeks;f.showWeeks?a.$parent.$watch(b(f.showWeeks),function(a){q=!!a,h()}):h(),f.min&&a.$parent.$watch(b(f.min),function(a){m.minDate=a?new Date(a):null,j()}),f.max&&a.$parent.$watch(b(f.max),function(a){m.maxDate=a?new Date(a):null,j()}),n.$render=function(){j(!0)},a.select=function(a){if(0===o){var b=n.$modelValue?new Date(n.$modelValue):new Date(0,0,0,0,0,0,0);b.setFullYear(a.getFullYear(),a.getMonth(),a.getDate()),n.$setViewValue(b),j(!0)}else p=a,k(o-1)},a.move=function(a){var b=m.modes[o].step;p.setMonth(p.getMonth()+a*(b.months||0)),p.setFullYear(p.getFullYear()+a*(b.years||0)),j()},a.toggleMode=function(){k((o+1)%m.modes.length)},a.getWeekNumber=function(b){return 0===o&&a.showWeekNumbers&&7===b.length?l(b[0].date):null}}}}}]).constant("datepickerPopupConfig",{dateFormat:"yyyy-MM-dd",currentText:"Today",toggleWeeksText:"Weeks",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","datepickerPopupConfig","datepickerConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",link:function(h,i,j,k){function l(a){u?u(h,!!a):q.isOpen=!!a}function m(a){if(a){if(angular.isDate(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=new Date(a);return isNaN(b)?(k.$setValidity("date",!1),void 0):(k.$setValidity("date",!0),b)}return k.$setValidity("date",!1),void 0}return k.$setValidity("date",!0),null}function n(a,c,d){a&&(h.$watch(b(a),function(a){q[c]=a}),y.attr(d||c,c))}function o(){q.position=s?d.offset(i):d.position(i),q.position.top=q.position.top+i.prop("offsetHeight")}var p,q=h.$new(),r=angular.isDefined(j.closeOnDateSelection)?h.$eval(j.closeOnDateSelection):f.closeOnDateSelection,s=angular.isDefined(j.datepickerAppendToBody)?h.$eval(j.datepickerAppendToBody):f.appendToBody;j.$observe("datepickerPopup",function(a){p=a||f.dateFormat,k.$render()}),q.showButtonBar=angular.isDefined(j.showButtonBar)?h.$eval(j.showButtonBar):f.showButtonBar,h.$on("$destroy",function(){C.remove(),q.$destroy()}),j.$observe("currentText",function(a){q.currentText=angular.isDefined(a)?a:f.currentText}),j.$observe("toggleWeeksText",function(a){q.toggleWeeksText=angular.isDefined(a)?a:f.toggleWeeksText}),j.$observe("clearText",function(a){q.clearText=angular.isDefined(a)?a:f.clearText}),j.$observe("closeText",function(a){q.closeText=angular.isDefined(a)?a:f.closeText});var t,u;j.isOpen&&(t=b(j.isOpen),u=t.assign,h.$watch(t,function(a){q.isOpen=!!a})),q.isOpen=t?t(h):!1;var v=function(a){q.isOpen&&a.target!==i[0]&&q.$apply(function(){l(!1)})},w=function(){q.$apply(function(){l(!0)})},x=angular.element("
      ");x.attr({"ng-model":"date","ng-change":"dateSelection()"});var y=angular.element(x.children()[0]),z={};j.datepickerOptions&&(z=h.$eval(j.datepickerOptions),y.attr(angular.extend({},z))),k.$parsers.unshift(m),q.dateSelection=function(a){angular.isDefined(a)&&(q.date=a),k.$setViewValue(q.date),k.$render(),r&&l(!1)},i.bind("input change keyup",function(){q.$apply(function(){q.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,p):"";i.val(a),q.date=k.$modelValue},n(j.min,"min"),n(j.max,"max"),j.showWeeks?n(j.showWeeks,"showWeeks","show-weeks"):(q.showWeeks="show-weeks"in z?z["show-weeks"]:g.showWeeks,y.attr("show-weeks","showWeeks")),j.dateDisabled&&y.attr("date-disabled",j.dateDisabled);var A=!1,B=!1;q.$watch("isOpen",function(a){a?(o(),c.bind("click",v),B&&i.unbind("focus",w),i[0].focus(),A=!0):(A&&c.unbind("click",v),i.bind("focus",w),B=!0),u&&u(h,a)}),q.today=function(){q.dateSelection(new Date)},q.clear=function(){q.dateSelection(null)};var C=a(x)(q);s?c.find("body").append(C):i.after(C)}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdownToggle",[]).directive("dropdownToggle",["$document","$location",function(a){var b=null,c=angular.noop;return{restrict:"CA",link:function(d,e){d.$watch("$location.path",function(){c()}),e.parent().bind("click",function(){c()}),e.bind("click",function(d){var f=e===b;d.preventDefault(),d.stopPropagation(),b&&c(),f||e.hasClass("disabled")||e.prop("disabled")||(e.parent().addClass("open"),b=e,c=function(d){d&&(d.preventDefault(),d.stopPropagation()),a.unbind("click",c),e.parent().removeClass("open"),c=angular.noop,b=null},a.bind("click",c))})}}}]),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0)}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g,0)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&e.$apply(function(){o.dismiss(b.key)}))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();h>=0&&!k&&(l=e.$new(!0),l.index=h,k=d("
      ")(l),f.append(k));var i=angular.element("
      ");i.attr("window-class",b.windowClass),i.attr("index",n.length()-1),i.attr("animate","animate"),i.html(b.content);var j=d(i)(b.scope);n.top().value.modalDomEl=j,f.append(j),f.addClass(m)},o.close=function(a,b){var c=n.get(a).value;c&&(c.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a).value;c&&(c.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,windowClass:b.windowClass})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse","$interpolate",function(a,b,c,d){var e=this,f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(d){b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){e.itemsPerPage=parseInt(b,10),a.totalPages=e.calculateTotalPages()}):this.itemsPerPage=d},this.noPrevious=function(){return 1===this.page},this.noNext=function(){return this.page===a.totalPages},this.isActive=function(a){return this.page===a},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.getAttributeValue=function(b,c,e){return angular.isDefined(b)?e?d(b)(a.$parent):a.$parent.$eval(b):c},this.render=function(){this.page=parseInt(a.page,10)||1,this.page>0&&this.page<=a.totalPages&&(a.pages=this.getPages(this.page,a.totalPages))},a.selectPage=function(b){!e.isActive(b)&&b>0&&b<=a.totalPages&&(a.page=b,a.onSelectPage({page:b}))},a.$watch("page",function(){e.render()}),a.$watch("totalItems",function(){a.totalPages=e.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),e.page>b?a.selectPage(b):e.render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{page:"=",totalItems:"=",onSelectPage:" &"},controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c,d){return{number:a,text:b,active:c,disabled:d}}var h,i=f.getAttributeValue(e.boundaryLinks,b.boundaryLinks),j=f.getAttributeValue(e.directionLinks,b.directionLinks),k=f.getAttributeValue(e.firstText,b.firstText,!0),l=f.getAttributeValue(e.previousText,b.previousText,!0),m=f.getAttributeValue(e.nextText,b.nextText,!0),n=f.getAttributeValue(e.lastText,b.lastText,!0),o=f.getAttributeValue(e.rotate,b.rotate);f.init(b.itemsPerPage),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){h=parseInt(a,10),f.render()}),f.getPages=function(a,b){var c=[],d=1,e=b,p=angular.isDefined(h)&&b>h;p&&(o?(d=Math.max(a-Math.floor(h/2),1),e=d+h-1,e>b&&(e=b,d=e-h+1)):(d=(Math.ceil(a/h)-1)*h+1,e=Math.min(d+h-1,b)));for(var q=d;e>=q;q++){var r=g(q,q,f.isActive(q),!1);c.push(r)}if(p&&!o){if(d>1){var s=g(d-1,"...",!1,!1);c.unshift(s)}if(b>e){var t=g(e+1,"...",!1,!1);c.push(t)}}if(j){var u=g(a-1,l,!1,f.noPrevious());c.unshift(u);var v=g(a+1,m,!1,f.noNext());c.push(v)}if(i){var w=g(1,k,!1,f.noPrevious());c.unshift(w);var x=g(b,n,!1,f.noNext());c.push(x)}return c}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{page:"=",totalItems:"=",onSelectPage:" &"},controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){function f(a,b,c,d,e){return{number:a,text:b,disabled:c,previous:i&&d,next:i&&e}}var g=e.getAttributeValue(d.previousText,a.previousText,!0),h=e.getAttributeValue(d.nextText,a.nextText,!0),i=e.getAttributeValue(d.align,a.align);e.init(a.itemsPerPage),e.getPages=function(a){return[f(a-1,g,e.noPrevious(),!0,!1),f(a+1,h,e.noNext(),!1,!0)]}}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$parse","$document","$position","$interpolate",function(e,f,g,h,i,j,k){return function(e,l,m){function n(a){var b=a||o.trigger||m,d=c[b]||b;return{show:b,hide:d}}var o=angular.extend({},b,d),p=a(e),q=k.startSymbol(),r=k.endSymbol(),s="
      ';return{restrict:"EA",scope:!0,compile:function(){var a=f(s);return function(b,c,d){function f(){b.tt_isOpen?m():k()}function k(){(!z||b.$eval(d[l+"Enable"]))&&(b.tt_popupDelay?(v=g(p,b.tt_popupDelay,!1),v.then(function(a){a()})):p()())}function m(){b.$apply(function(){q()})}function p(){return b.tt_content?(r(),u&&g.cancel(u),t.css({top:0,left:0,display:"block"}),w?i.find("body").append(t):c.after(t),A(),b.tt_isOpen=!0,b.$digest(),A):angular.noop}function q(){b.tt_isOpen=!1,g.cancel(v),b.tt_animation?u=g(s,500):s()}function r(){t&&s(),t=a(b,function(){}),b.$digest()}function s(){t&&(t.remove(),t=null)}var t,u,v,w=angular.isDefined(o.appendToBody)?o.appendToBody:!1,x=n(void 0),y=!1,z=angular.isDefined(d[l+"Enable"]),A=function(){var a,d,e,f;switch(a=w?j.offset(c):j.position(c),d=t.prop("offsetWidth"),e=t.prop("offsetHeight"),b.tt_placement){case"right":f={top:a.top+a.height/2-e/2,left:a.left+a.width};break;case"bottom":f={top:a.top+a.height,left:a.left+a.width/2-d/2};break;case"left":f={top:a.top+a.height/2-e/2,left:a.left-d};break;default:f={top:a.top-e,left:a.left+a.width/2-d/2}}f.top+="px",f.left+="px",t.css(f)};b.tt_isOpen=!1,d.$observe(e,function(a){b.tt_content=a,!a&&b.tt_isOpen&&q()}),d.$observe(l+"Title",function(a){b.tt_title=a}),d.$observe(l+"Placement",function(a){b.tt_placement=angular.isDefined(a)?a:o.placement}),d.$observe(l+"PopupDelay",function(a){var c=parseInt(a,10);b.tt_popupDelay=isNaN(c)?o.popupDelay:c});var B=function(){y&&(c.unbind(x.show,k),c.unbind(x.hide,m))};d.$observe(l+"Trigger",function(a){B(),x=n(a),x.show===x.hide?c.bind(x.show,f):(c.bind(x.show,k),c.bind(x.hide,m)),y=!0});var C=b.$eval(d[l+"Animation"]);b.tt_animation=angular.isDefined(C)?!!C:o.animation,d.$observe(l+"AppendToBody",function(a){w=angular.isDefined(a)?h(a)(b):w}),w&&b.$on("$locationChangeSuccess",function(){b.tt_isOpen&&q()}),b.$on("$destroy",function(){g.cancel(u),g.cancel(v),B(),s()})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",["ui.bootstrap.transition"]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig","$transition",function(a,b,c,d){var e=this,f=[],g=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,h=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.addBar=function(a,b){var c=0,d=a.$parent.$index;angular.isDefined(d)&&f[d]&&(c=f[d].value),f.push(a),this.update(b,a.value,c),a.$watch("value",function(a,c){a!==c&&e.update(b,a,c)}),a.$on("$destroy",function(){e.removeBar(a)})},this.update=function(a,b,c){var e=this.getPercentage(b);h?(a.css("width",this.getPercentage(c)+"%"),d(a,{width:e+"%"})):a.css({transition:"none",width:e+"%"})},this.removeBar=function(a){f.splice(f.indexOf(a),1)},this.getPercentage=function(a){return Math.round(100*a/g)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},template:'
      '}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","$parse","ratingConfig",function(a,b,c,d){this.maxRange=angular.isDefined(b.max)?a.$parent.$eval(b.max):d.max,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):d.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):d.stateOff,this.createRateObjects=function(a){for(var b={stateOn:this.stateOn,stateOff:this.stateOff},c=0,d=a.length;d>c;c++)a[c]=angular.extend({index:c},b,a[c]);return a},a.range=angular.isDefined(b.ratingStates)?this.createRateObjects(angular.copy(a.$parent.$eval(b.ratingStates))):this.createRateObjects(new Array(this.maxRange)),a.rate=function(b){a.value===b||a.readonly||(a.value=b)},a.enter=function(b){a.readonly||(a.val=b),a.onHover({value:b})},a.reset=function(){a.val=angular.copy(a.value),a.onLeave()},a.$watch("value",function(b){a.val=b}),a.readonly=!1,b.readonly&&a.$parent.$watch(c(b.readonly),function(b){a.readonly=!!b})}]).directive("rating",function(){return{restrict:"EA",scope:{value:"=",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(a){a.active=!1}),a.active=!0},b.addTab=function(a){c.push(a),(1===c.length||a.active)&&b.select(a)},b.removeTab=function(a){var d=c.indexOf(a);if(a.active&&c.length>1){var e=d==c.length-1?d-1:d+1;b.select(c[e])}c.splice(d,1)}}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1,a.type=angular.isDefined(c.type)?a.$parent.$eval(c.type):"tabs" +}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){var g,h;e.active?(g=a(e.active),h=g.assign,b.$parent.$watch(g,function(a,c){a!==c&&(b.active=!!a)}),b.active=g(b.$parent)):h=g=angular.noop,b.$watch("active",function(a){h(b.$parent,a),a?(f.select(b),b.onSelect()):b.onDeselect()}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).directive("timepicker",["$parse","$log","timepickerConfig","$locale",function(a,b,c,d){return{restrict:"EA",require:"?^ngModel",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(e,f,g,h){function i(){var a=parseInt(e.hours,10),b=e.showMeridian?a>0&&13>a:a>=0&&24>a;return b?(e.showMeridian&&(12===a&&(a=0),e.meridian===q[1]&&(a+=12)),a):void 0}function j(){var a=parseInt(e.minutes,10);return a>=0&&60>a?a:void 0}function k(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function l(a){m(),h.$setViewValue(new Date(p)),n(a)}function m(){h.$setValidity("time",!0),e.invalidHours=!1,e.invalidMinutes=!1}function n(a){var b=p.getHours(),c=p.getMinutes();e.showMeridian&&(b=0===b||12===b?12:b%12),e.hours="h"===a?b:k(b),e.minutes="m"===a?c:k(c),e.meridian=p.getHours()<12?q[0]:q[1]}function o(a){var b=new Date(p.getTime()+6e4*a);p.setHours(b.getHours(),b.getMinutes()),l()}if(h){var p=new Date,q=angular.isDefined(g.meridians)?e.$parent.$eval(g.meridians):c.meridians||d.DATETIME_FORMATS.AMPMS,r=c.hourStep;g.hourStep&&e.$parent.$watch(a(g.hourStep),function(a){r=parseInt(a,10)});var s=c.minuteStep;g.minuteStep&&e.$parent.$watch(a(g.minuteStep),function(a){s=parseInt(a,10)}),e.showMeridian=c.showMeridian,g.showMeridian&&e.$parent.$watch(a(g.showMeridian),function(a){if(e.showMeridian=!!a,h.$error.time){var b=i(),c=j();angular.isDefined(b)&&angular.isDefined(c)&&(p.setHours(b),l())}else n()});var t=f.find("input"),u=t.eq(0),v=t.eq(1),w=angular.isDefined(g.mousewheel)?e.$eval(g.mousewheel):c.mousewheel;if(w){var x=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};u.bind("mousewheel wheel",function(a){e.$apply(x(a)?e.incrementHours():e.decrementHours()),a.preventDefault()}),v.bind("mousewheel wheel",function(a){e.$apply(x(a)?e.incrementMinutes():e.decrementMinutes()),a.preventDefault()})}if(e.readonlyInput=angular.isDefined(g.readonlyInput)?e.$eval(g.readonlyInput):c.readonlyInput,e.readonlyInput)e.updateHours=angular.noop,e.updateMinutes=angular.noop;else{var y=function(a,b){h.$setViewValue(null),h.$setValidity("time",!1),angular.isDefined(a)&&(e.invalidHours=a),angular.isDefined(b)&&(e.invalidMinutes=b)};e.updateHours=function(){var a=i();angular.isDefined(a)?(p.setHours(a),l("h")):y(!0)},u.bind("blur",function(){!e.validHours&&e.hours<10&&e.$apply(function(){e.hours=k(e.hours)})}),e.updateMinutes=function(){var a=j();angular.isDefined(a)?(p.setMinutes(a),l("m")):y(void 0,!0)},v.bind("blur",function(){!e.invalidMinutes&&e.minutes<10&&e.$apply(function(){e.minutes=k(e.minutes)})})}h.$render=function(){var a=h.$modelValue?new Date(h.$modelValue):null;isNaN(a)?(h.$setValidity("time",!1),b.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(p=a),m(),n())},e.incrementHours=function(){o(60*r)},e.decrementHours=function(){o(60*-r)},e.incrementMinutes=function(){o(s)},e.decrementMinutes=function(){o(-s)},e.toggleMeridian=function(){o(720*(p.getHours()<12?1:-1))}}}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error("Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_' but got '"+c+"'.");return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?b(k.typeaheadAppendToBody):!1,u=b(k.ngModel).assign,v=g.parse(k.typeahead),w=angular.element("
      ");w.attr({matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&w.attr("template-url",k.typeaheadTemplateUrl);var x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y=function(){x.matches=[],x.activeIdx=-1},z=function(a){var b={$viewValue:a};q(i,!0),c.when(v.source(i,b)).then(function(c){if(a===l.$viewValue&&m){if(c.length>0){x.activeIdx=0,x.matches.length=0;for(var d=0;d=n?o>0?(A&&d.cancel(A),A=d(function(){z(a)},o)):z(a):(q(i,!1),y()),p?a:a?(l.$setValidity("editable",!1),void 0):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[v.itemName]=a,b=v.viewMapper(i,d),d[v.itemName]=void 0,c=v.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,d={};d[v.itemName]=c=x.matches[a].model,b=v.modelMapper(i,d),u(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:v.viewMapper(i,d)}),y(),j[0].focus()},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),y(),x.$digest()))}),j.bind("blur",function(){m=!1});var B=function(a){j[0]!==a.target&&(y(),x.$digest())};e.bind("click",B),i.$on("$destroy",function(){e.unbind("click",B)});var C=a(w)(x);t?e.find("body").append(C):j.after(C)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?b.replace(new RegExp(a(c),"gi"),"$&"):b}}); \ No newline at end of file diff --git a/dist/bower_components/angular-cookies/.bower.json b/dist/bower_components/angular-cookies/.bower.json new file mode 100644 index 000000000..4f69feb2b --- /dev/null +++ b/dist/bower_components/angular-cookies/.bower.json @@ -0,0 +1,18 @@ +{ + "name": "angular-cookies", + "version": "1.2.16", + "main": "./angular-cookies.js", + "dependencies": { + "angular": "1.2.16" + }, + "homepage": "https://github.com/angular/bower-angular-cookies", + "_release": "1.2.16", + "_resolution": { + "type": "version", + "tag": "v1.2.16", + "commit": "8515dbd25c3b0a9d334f657849e4a7ec609bf91b" + }, + "_source": "git://github.com/angular/bower-angular-cookies.git", + "_target": "~1.2.8", + "_originalSource": "angular-cookies" +} \ No newline at end of file diff --git a/dist/bower_components/angular-cookies/README.md b/dist/bower_components/angular-cookies/README.md new file mode 100644 index 000000000..77c71f4d8 --- /dev/null +++ b/dist/bower_components/angular-cookies/README.md @@ -0,0 +1,54 @@ +# bower-angular-cookies + +This repo is for distribution on `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngCookies). +Please file issues and pull requests against that repo. + +## Install + +Install with `bower`: + +```shell +bower install angular-cookies +``` + +Add a ` +``` + +And add `ngCookies` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngCookies']); +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/api/ngCookies). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist/bower_components/angular-cookies/angular-cookies.js b/dist/bower_components/angular-cookies/angular-cookies.js new file mode 100644 index 000000000..f43d44dc8 --- /dev/null +++ b/dist/bower_components/angular-cookies/angular-cookies.js @@ -0,0 +1,196 @@ +/** + * @license AngularJS v1.2.16 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +/** + * @ngdoc module + * @name ngCookies + * @description + * + * # ngCookies + * + * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies. + * + * + *
      + * + * See {@link ngCookies.$cookies `$cookies`} and + * {@link ngCookies.$cookieStore `$cookieStore`} for usage. + */ + + +angular.module('ngCookies', ['ng']). + /** + * @ngdoc service + * @name $cookies + * + * @description + * Provides read/write access to browser's cookies. + * + * Only a simple Object is exposed and by adding or removing properties to/from this object, new + * cookies are created/deleted at the end of current $eval. + * The object's properties can only be strings. + * + * Requires the {@link ngCookies `ngCookies`} module to be installed. + * + * @example + + + + + + */ + factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) { + var cookies = {}, + lastCookies = {}, + lastBrowserCookies, + runEval = false, + copy = angular.copy, + isUndefined = angular.isUndefined; + + //creates a poller fn that copies all cookies from the $browser to service & inits the service + $browser.addPollFn(function() { + var currentCookies = $browser.cookies(); + if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl + lastBrowserCookies = currentCookies; + copy(currentCookies, lastCookies); + copy(currentCookies, cookies); + if (runEval) $rootScope.$apply(); + } + })(); + + runEval = true; + + //at the end of each eval, push cookies + //TODO: this should happen before the "delayed" watches fire, because if some cookies are not + // strings or browser refuses to store some cookies, we update the model in the push fn. + $rootScope.$watch(push); + + return cookies; + + + /** + * Pushes all the cookies from the service to the browser and verifies if all cookies were + * stored. + */ + function push() { + var name, + value, + browserCookies, + updated; + + //delete any cookies deleted in $cookies + for (name in lastCookies) { + if (isUndefined(cookies[name])) { + $browser.cookies(name, undefined); + } + } + + //update all cookies updated in $cookies + for(name in cookies) { + value = cookies[name]; + if (!angular.isString(value)) { + value = '' + value; + cookies[name] = value; + } + if (value !== lastCookies[name]) { + $browser.cookies(name, value); + updated = true; + } + } + + //verify what was actually stored + if (updated){ + updated = false; + browserCookies = $browser.cookies(); + + for (name in cookies) { + if (cookies[name] !== browserCookies[name]) { + //delete or reset all cookies that the browser dropped from $cookies + if (isUndefined(browserCookies[name])) { + delete cookies[name]; + } else { + cookies[name] = browserCookies[name]; + } + updated = true; + } + } + } + } + }]). + + + /** + * @ngdoc service + * @name $cookieStore + * @requires $cookies + * + * @description + * Provides a key-value (string-object) storage, that is backed by session cookies. + * Objects put or retrieved from this storage are automatically serialized or + * deserialized by angular's toJson/fromJson. + * + * Requires the {@link ngCookies `ngCookies`} module to be installed. + * + * @example + */ + factory('$cookieStore', ['$cookies', function($cookies) { + + return { + /** + * @ngdoc method + * @name $cookieStore#get + * + * @description + * Returns the value of given cookie key + * + * @param {string} key Id to use for lookup. + * @returns {Object} Deserialized cookie value. + */ + get: function(key) { + var value = $cookies[key]; + return value ? angular.fromJson(value) : value; + }, + + /** + * @ngdoc method + * @name $cookieStore#put + * + * @description + * Sets a value for given cookie key + * + * @param {string} key Id for the `value`. + * @param {Object} value Value to be stored. + */ + put: function(key, value) { + $cookies[key] = angular.toJson(value); + }, + + /** + * @ngdoc method + * @name $cookieStore#remove + * + * @description + * Remove given cookie + * + * @param {string} key Id of the key-value pair to delete. + */ + remove: function(key) { + delete $cookies[key]; + } + }; + + }]); + + +})(window, window.angular); diff --git a/dist/bower_components/angular-cookies/angular-cookies.min.js b/dist/bower_components/angular-cookies/angular-cookies.min.js new file mode 100644 index 000000000..4d4527f32 --- /dev/null +++ b/dist/bower_components/angular-cookies/angular-cookies.min.js @@ -0,0 +1,8 @@ +/* + AngularJS v1.2.16 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(e,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&e.$apply())})();k=!0;e.$watch(function(){var a,d,e;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)d=c[a],f.isString(d)||(d=""+d,c[a]=d),d!==g[a]&&(b.cookies(a,d),e=!0);if(e)for(a in d=b.cookies(),c)c[a]!==d[a]&&(m(d[a])?delete c[a]:c[a]=d[a])});return c}]).factory("$cookieStore", +["$cookies",function(e){return{get:function(b){return(b=e[b])?f.fromJson(b):b},put:function(b,c){e[b]=f.toJson(c)},remove:function(b){delete e[b]}}}])})(window,window.angular); +//# sourceMappingURL=angular-cookies.min.js.map diff --git a/dist/bower_components/angular-cookies/angular-cookies.min.js.map b/dist/bower_components/angular-cookies/angular-cookies.min.js.map new file mode 100644 index 000000000..1d3c5d32c --- /dev/null +++ b/dist/bower_components/angular-cookies/angular-cookies.min.js.map @@ -0,0 +1,8 @@ +{ +"version":3, +"file":"angular-cookies.min.js", +"lineCount":7, +"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAmBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA4BW,UA5BX,CA4BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAS,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACxEC,EAAU,EAD8D,CAExEC,EAAc,EAF0D,CAGxEC,CAHwE,CAIxEC,EAAU,CAAA,CAJ8D,CAKxEC,EAAOV,CAAAU,KALiE,CAMxEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAIgB,CAAJ,GAAYX,EAAZ,CACEY,CAKA,CALQZ,CAAA,CAAQW,CAAR,CAKR,CAJKjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAIL,GAHEA,CACA,CADQ,EACR,CADaA,CACb,CAAAZ,CAAA,CAAQW,CAAR,CAAA,CAAgBC,CAElB,EAAIA,CAAJ,GAAcX,CAAA,CAAYU,CAAZ,CAAd,GACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CAFZ,CAOF,IAAIA,CAAJ,CAIE,IAAKF,CAAL,GAFAI,EAEaf,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBI,CAAA,CAAeJ,CAAf,CAAtB,GAEMN,CAAA,CAAYU,CAAA,CAAeJ,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBI,CAAA,CAAeJ,CAAf,CALpB,CAhCU,CAThB,CAEA,OAAOX,EA1BqE,CAA3D,CA5BvB,CAAAH,QAAA,CA0HW,cA1HX;AA0H2B,CAAC,UAAD,CAAa,QAAQ,CAACmB,CAAD,CAAW,CAErD,MAAO,KAWAC,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHN,CACG,CADKI,CAAA,CAASE,CAAT,CACL,EAAQxB,CAAAyB,SAAA,CAAiBP,CAAjB,CAAR,CAAkCA,CAFxB,CAXd,KA0BAQ,QAAQ,CAACF,CAAD,CAAMN,CAAN,CAAa,CACxBI,CAAA,CAASE,CAAT,CAAA,CAAgBxB,CAAA2B,OAAA,CAAeT,CAAf,CADQ,CA1BrB,QAuCGU,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CAvCjB,CAF8C,CAAhC,CA1H3B,CAnBsC,CAArC,CAAA,CA8LEzB,MA9LF,CA8LUA,MAAAC,QA9LV;", +"sources":["angular-cookies.js"], +"names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"] +} diff --git a/dist/bower_components/angular-cookies/bower.json b/dist/bower_components/angular-cookies/bower.json new file mode 100644 index 000000000..cf5f05a0d --- /dev/null +++ b/dist/bower_components/angular-cookies/bower.json @@ -0,0 +1,8 @@ +{ + "name": "angular-cookies", + "version": "1.2.16", + "main": "./angular-cookies.js", + "dependencies": { + "angular": "1.2.16" + } +} diff --git a/dist/bower_components/angular-mocks/.bower.json b/dist/bower_components/angular-mocks/.bower.json new file mode 100644 index 000000000..20419484c --- /dev/null +++ b/dist/bower_components/angular-mocks/.bower.json @@ -0,0 +1,18 @@ +{ + "name": "angular-mocks", + "version": "1.2.8", + "main": "./angular-mocks.js", + "dependencies": { + "angular": "1.2.8" + }, + "homepage": "https://github.com/angular/bower-angular-mocks", + "_release": "1.2.8", + "_resolution": { + "type": "version", + "tag": "v1.2.8", + "commit": "96a60096da4b80fe14292cbbeed585119f0e9b43" + }, + "_source": "git://github.com/angular/bower-angular-mocks.git", + "_target": "1.2.8", + "_originalSource": "angular-mocks" +} \ No newline at end of file diff --git a/dist/bower_components/angular-mocks/README.md b/dist/bower_components/angular-mocks/README.md new file mode 100644 index 000000000..3448d2849 --- /dev/null +++ b/dist/bower_components/angular-mocks/README.md @@ -0,0 +1,42 @@ +# bower-angular-mocks + +This repo is for distribution on `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngMock). +Please file issues and pull requests against that repo. + +## Install + +Install with `bower`: + +```shell +bower install angular-mocks +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/guide/dev_guide.unit-testing). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist/bower_components/angular-mocks/angular-mocks.js b/dist/bower_components/angular-mocks/angular-mocks.js new file mode 100644 index 000000000..90ae18663 --- /dev/null +++ b/dist/bower_components/angular-mocks/angular-mocks.js @@ -0,0 +1,2136 @@ +/** + * @license AngularJS v1.2.8 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) { + +'use strict'; + +/** + * @ngdoc overview + * @name angular.mock + * @description + * + * Namespace from 'angular-mocks.js' which contains testing related code. + */ +angular.mock = {}; + +/** + * ! This is a private undocumented service ! + * + * @name ngMock.$browser + * + * @description + * This service is a mock implementation of {@link ng.$browser}. It provides fake + * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr, + * cookies, etc... + * + * The api of this service is the same as that of the real {@link ng.$browser $browser}, except + * that there are several helper methods available which can be used in tests. + */ +angular.mock.$BrowserProvider = function() { + this.$get = function() { + return new angular.mock.$Browser(); + }; +}; + +angular.mock.$Browser = function() { + var self = this; + + this.isMock = true; + self.$$url = "http://server/"; + self.$$lastUrl = self.$$url; // used by url polling fn + self.pollFns = []; + + // TODO(vojta): remove this temporary api + self.$$completeOutstandingRequest = angular.noop; + self.$$incOutstandingRequestCount = angular.noop; + + + // register url polling fn + + self.onUrlChange = function(listener) { + self.pollFns.push( + function() { + if (self.$$lastUrl != self.$$url) { + self.$$lastUrl = self.$$url; + listener(self.$$url); + } + } + ); + + return listener; + }; + + self.cookieHash = {}; + self.lastCookieHash = {}; + self.deferredFns = []; + self.deferredNextId = 0; + + self.defer = function(fn, delay) { + delay = delay || 0; + self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId}); + self.deferredFns.sort(function(a,b){ return a.time - b.time;}); + return self.deferredNextId++; + }; + + + /** + * @name ngMock.$browser#defer.now + * @propertyOf ngMock.$browser + * + * @description + * Current milliseconds mock time. + */ + self.defer.now = 0; + + + self.defer.cancel = function(deferId) { + var fnIndex; + + angular.forEach(self.deferredFns, function(fn, index) { + if (fn.id === deferId) fnIndex = index; + }); + + if (fnIndex !== undefined) { + self.deferredFns.splice(fnIndex, 1); + return true; + } + + return false; + }; + + + /** + * @name ngMock.$browser#defer.flush + * @methodOf ngMock.$browser + * + * @description + * Flushes all pending requests and executes the defer callbacks. + * + * @param {number=} number of milliseconds to flush. See {@link #defer.now} + */ + self.defer.flush = function(delay) { + if (angular.isDefined(delay)) { + self.defer.now += delay; + } else { + if (self.deferredFns.length) { + self.defer.now = self.deferredFns[self.deferredFns.length-1].time; + } else { + throw new Error('No deferred tasks to be flushed'); + } + } + + while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) { + self.deferredFns.shift().fn(); + } + }; + + self.$$baseHref = ''; + self.baseHref = function() { + return this.$$baseHref; + }; +}; +angular.mock.$Browser.prototype = { + +/** + * @name ngMock.$browser#poll + * @methodOf ngMock.$browser + * + * @description + * run all fns in pollFns + */ + poll: function poll() { + angular.forEach(this.pollFns, function(pollFn){ + pollFn(); + }); + }, + + addPollFn: function(pollFn) { + this.pollFns.push(pollFn); + return pollFn; + }, + + url: function(url, replace) { + if (url) { + this.$$url = url; + return this; + } + + return this.$$url; + }, + + cookies: function(name, value) { + if (name) { + if (angular.isUndefined(value)) { + delete this.cookieHash[name]; + } else { + if (angular.isString(value) && //strings only + value.length <= 4096) { //strict cookie storage limits + this.cookieHash[name] = value; + } + } + } else { + if (!angular.equals(this.cookieHash, this.lastCookieHash)) { + this.lastCookieHash = angular.copy(this.cookieHash); + this.cookieHash = angular.copy(this.cookieHash); + } + return this.cookieHash; + } + }, + + notifyWhenNoOutstandingRequests: function(fn) { + fn(); + } +}; + + +/** + * @ngdoc object + * @name ngMock.$exceptionHandlerProvider + * + * @description + * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors + * passed into the `$exceptionHandler`. + */ + +/** + * @ngdoc object + * @name ngMock.$exceptionHandler + * + * @description + * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed + * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration + * information. + * + * + *
      + *   describe('$exceptionHandlerProvider', function() {
      + *
      + *     it('should capture log messages and exceptions', function() {
      + *
      + *       module(function($exceptionHandlerProvider) {
      + *         $exceptionHandlerProvider.mode('log');
      + *       });
      + *
      + *       inject(function($log, $exceptionHandler, $timeout) {
      + *         $timeout(function() { $log.log(1); });
      + *         $timeout(function() { $log.log(2); throw 'banana peel'; });
      + *         $timeout(function() { $log.log(3); });
      + *         expect($exceptionHandler.errors).toEqual([]);
      + *         expect($log.assertEmpty());
      + *         $timeout.flush();
      + *         expect($exceptionHandler.errors).toEqual(['banana peel']);
      + *         expect($log.log.logs).toEqual([[1], [2], [3]]);
      + *       });
      + *     });
      + *   });
      + * 
      + */ + +angular.mock.$ExceptionHandlerProvider = function() { + var handler; + + /** + * @ngdoc method + * @name ngMock.$exceptionHandlerProvider#mode + * @methodOf ngMock.$exceptionHandlerProvider + * + * @description + * Sets the logging mode. + * + * @param {string} mode Mode of operation, defaults to `rethrow`. + * + * - `rethrow`: If any errors are passed into the handler in tests, it typically + * means that there is a bug in the application or test, so this mock will + * make these tests fail. + * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` + * mode stores an array of errors in `$exceptionHandler.errors`, to allow later + * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and + * {@link ngMock.$log#reset reset()} + */ + this.mode = function(mode) { + switch(mode) { + case 'rethrow': + handler = function(e) { + throw e; + }; + break; + case 'log': + var errors = []; + + handler = function(e) { + if (arguments.length == 1) { + errors.push(e); + } else { + errors.push([].slice.call(arguments, 0)); + } + }; + + handler.errors = errors; + break; + default: + throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!"); + } + }; + + this.$get = function() { + return handler; + }; + + this.mode('rethrow'); +}; + + +/** + * @ngdoc service + * @name ngMock.$log + * + * @description + * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays + * (one array per logging level). These arrays are exposed as `logs` property of each of the + * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`. + * + */ +angular.mock.$LogProvider = function() { + var debug = true; + + function concat(array1, array2, index) { + return array1.concat(Array.prototype.slice.call(array2, index)); + } + + this.debugEnabled = function(flag) { + if (angular.isDefined(flag)) { + debug = flag; + return this; + } else { + return debug; + } + }; + + this.$get = function () { + var $log = { + log: function() { $log.log.logs.push(concat([], arguments, 0)); }, + warn: function() { $log.warn.logs.push(concat([], arguments, 0)); }, + info: function() { $log.info.logs.push(concat([], arguments, 0)); }, + error: function() { $log.error.logs.push(concat([], arguments, 0)); }, + debug: function() { + if (debug) { + $log.debug.logs.push(concat([], arguments, 0)); + } + } + }; + + /** + * @ngdoc method + * @name ngMock.$log#reset + * @methodOf ngMock.$log + * + * @description + * Reset all of the logging arrays to empty. + */ + $log.reset = function () { + /** + * @ngdoc property + * @name ngMock.$log#log.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#log}. + * + * @example + *
      +       * $log.log('Some Log');
      +       * var first = $log.log.logs.unshift();
      +       * 
      + */ + $log.log.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#info.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#info}. + * + * @example + *
      +       * $log.info('Some Info');
      +       * var first = $log.info.logs.unshift();
      +       * 
      + */ + $log.info.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#warn.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#warn}. + * + * @example + *
      +       * $log.warn('Some Warning');
      +       * var first = $log.warn.logs.unshift();
      +       * 
      + */ + $log.warn.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#error.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#error}. + * + * @example + *
      +       * $log.log('Some Error');
      +       * var first = $log.error.logs.unshift();
      +       * 
      + */ + $log.error.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#debug.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#debug}. + * + * @example + *
      +       * $log.debug('Some Error');
      +       * var first = $log.debug.logs.unshift();
      +       * 
      + */ + $log.debug.logs = []; + }; + + /** + * @ngdoc method + * @name ngMock.$log#assertEmpty + * @methodOf ngMock.$log + * + * @description + * Assert that the all of the logging methods have no logged messages. If messages present, an + * exception is thrown. + */ + $log.assertEmpty = function() { + var errors = []; + angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) { + angular.forEach($log[logLevel].logs, function(log) { + angular.forEach(log, function (logItem) { + errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + + (logItem.stack || '')); + }); + }); + }); + if (errors.length) { + errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or "+ + "an expected log message was not checked and removed:"); + errors.push(''); + throw new Error(errors.join('\n---------\n')); + } + }; + + $log.reset(); + return $log; + }; +}; + + +/** + * @ngdoc service + * @name ngMock.$interval + * + * @description + * Mock implementation of the $interval service. + * + * Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to + * move forward by `millis` milliseconds and trigger any functions scheduled to run in that + * time. + * + * @param {function()} fn A function that should be called repeatedly. + * @param {number} delay Number of milliseconds between each function call. + * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat + * indefinitely. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block. + * @returns {promise} A promise which will be notified on each iteration. + */ +angular.mock.$IntervalProvider = function() { + this.$get = ['$rootScope', '$q', + function($rootScope, $q) { + var repeatFns = [], + nextRepeatId = 0, + now = 0; + + var $interval = function(fn, delay, count, invokeApply) { + var deferred = $q.defer(), + promise = deferred.promise, + iteration = 0, + skipApply = (angular.isDefined(invokeApply) && !invokeApply); + + count = (angular.isDefined(count)) ? count : 0, + promise.then(null, null, fn); + + promise.$$intervalId = nextRepeatId; + + function tick() { + deferred.notify(iteration++); + + if (count > 0 && iteration >= count) { + var fnIndex; + deferred.resolve(iteration); + + angular.forEach(repeatFns, function(fn, index) { + if (fn.id === promise.$$intervalId) fnIndex = index; + }); + + if (fnIndex !== undefined) { + repeatFns.splice(fnIndex, 1); + } + } + + if (!skipApply) $rootScope.$apply(); + } + + repeatFns.push({ + nextTime:(now + delay), + delay: delay, + fn: tick, + id: nextRepeatId, + deferred: deferred + }); + repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); + + nextRepeatId++; + return promise; + }; + + $interval.cancel = function(promise) { + var fnIndex; + + angular.forEach(repeatFns, function(fn, index) { + if (fn.id === promise.$$intervalId) fnIndex = index; + }); + + if (fnIndex !== undefined) { + repeatFns[fnIndex].deferred.reject('canceled'); + repeatFns.splice(fnIndex, 1); + return true; + } + + return false; + }; + + /** + * @ngdoc method + * @name ngMock.$interval#flush + * @methodOf ngMock.$interval + * @description + * + * Runs interval tasks scheduled to be run in the next `millis` milliseconds. + * + * @param {number=} millis maximum timeout amount to flush up until. + * + * @return {number} The amount of time moved forward. + */ + $interval.flush = function(millis) { + now += millis; + while (repeatFns.length && repeatFns[0].nextTime <= now) { + var task = repeatFns[0]; + task.fn(); + task.nextTime += task.delay; + repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); + } + return millis; + }; + + return $interval; + }]; +}; + + +/* jshint -W101 */ +/* The R_ISO8061_STR regex is never going to fit into the 100 char limit! + * This directive should go inside the anonymous function but a bug in JSHint means that it would + * not be enacted early enough to prevent the warning. + */ +var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/; + +function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8061_STR)) { + var date = new Date(0), + tzHour = 0, + tzMin = 0; + if (match[9]) { + tzHour = int(match[9] + match[10]); + tzMin = int(match[9] + match[11]); + } + date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3])); + date.setUTCHours(int(match[4]||0) - tzHour, + int(match[5]||0) - tzMin, + int(match[6]||0), + int(match[7]||0)); + return date; + } + return string; +} + +function int(str) { + return parseInt(str, 10); +} + +function padNumber(num, digits, trim) { + var neg = ''; + if (num < 0) { + neg = '-'; + num = -num; + } + num = '' + num; + while(num.length < digits) num = '0' + num; + if (trim) + num = num.substr(num.length - digits); + return neg + num; +} + + +/** + * @ngdoc object + * @name angular.mock.TzDate + * @description + * + * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`. + * + * Mock of the Date type which has its timezone specified via constructor arg. + * + * The main purpose is to create Date-like instances with timezone fixed to the specified timezone + * offset, so that we can test code that depends on local timezone settings without dependency on + * the time zone settings of the machine where the code is running. + * + * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored) + * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* + * + * @example + * !!!! WARNING !!!!! + * This is not a complete Date object so only methods that were implemented can be called safely. + * To make matters worse, TzDate instances inherit stuff from Date via a prototype. + * + * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is + * incomplete we might be missing some non-standard methods. This can result in errors like: + * "Date.prototype.foo called on incompatible Object". + * + *
      + * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
      + * newYearInBratislava.getTimezoneOffset() => -60;
      + * newYearInBratislava.getFullYear() => 2010;
      + * newYearInBratislava.getMonth() => 0;
      + * newYearInBratislava.getDate() => 1;
      + * newYearInBratislava.getHours() => 0;
      + * newYearInBratislava.getMinutes() => 0;
      + * newYearInBratislava.getSeconds() => 0;
      + * 
      + * + */ +angular.mock.TzDate = function (offset, timestamp) { + var self = new Date(0); + if (angular.isString(timestamp)) { + var tsStr = timestamp; + + self.origDate = jsonStringToDate(timestamp); + + timestamp = self.origDate.getTime(); + if (isNaN(timestamp)) + throw { + name: "Illegal Argument", + message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string" + }; + } else { + self.origDate = new Date(timestamp); + } + + var localOffset = new Date(timestamp).getTimezoneOffset(); + self.offsetDiff = localOffset*60*1000 - offset*1000*60*60; + self.date = new Date(timestamp + self.offsetDiff); + + self.getTime = function() { + return self.date.getTime() - self.offsetDiff; + }; + + self.toLocaleDateString = function() { + return self.date.toLocaleDateString(); + }; + + self.getFullYear = function() { + return self.date.getFullYear(); + }; + + self.getMonth = function() { + return self.date.getMonth(); + }; + + self.getDate = function() { + return self.date.getDate(); + }; + + self.getHours = function() { + return self.date.getHours(); + }; + + self.getMinutes = function() { + return self.date.getMinutes(); + }; + + self.getSeconds = function() { + return self.date.getSeconds(); + }; + + self.getMilliseconds = function() { + return self.date.getMilliseconds(); + }; + + self.getTimezoneOffset = function() { + return offset * 60; + }; + + self.getUTCFullYear = function() { + return self.origDate.getUTCFullYear(); + }; + + self.getUTCMonth = function() { + return self.origDate.getUTCMonth(); + }; + + self.getUTCDate = function() { + return self.origDate.getUTCDate(); + }; + + self.getUTCHours = function() { + return self.origDate.getUTCHours(); + }; + + self.getUTCMinutes = function() { + return self.origDate.getUTCMinutes(); + }; + + self.getUTCSeconds = function() { + return self.origDate.getUTCSeconds(); + }; + + self.getUTCMilliseconds = function() { + return self.origDate.getUTCMilliseconds(); + }; + + self.getDay = function() { + return self.date.getDay(); + }; + + // provide this method only on browsers that already have it + if (self.toISOString) { + self.toISOString = function() { + return padNumber(self.origDate.getUTCFullYear(), 4) + '-' + + padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' + + padNumber(self.origDate.getUTCDate(), 2) + 'T' + + padNumber(self.origDate.getUTCHours(), 2) + ':' + + padNumber(self.origDate.getUTCMinutes(), 2) + ':' + + padNumber(self.origDate.getUTCSeconds(), 2) + '.' + + padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'; + }; + } + + //hide all methods not implemented in this mock that the Date prototype exposes + var unimplementedMethods = ['getUTCDay', + 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', + 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', + 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', + 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString', + 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf']; + + angular.forEach(unimplementedMethods, function(methodName) { + self[methodName] = function() { + throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock"); + }; + }); + + return self; +}; + +//make "tzDateInstance instanceof Date" return true +angular.mock.TzDate.prototype = Date.prototype; +/* jshint +W101 */ + +angular.mock.animate = angular.module('mock.animate', ['ng']) + + .config(['$provide', function($provide) { + + $provide.decorator('$animate', function($delegate) { + var animate = { + queue : [], + enabled : $delegate.enabled, + flushNext : function(name) { + var tick = animate.queue.shift(); + + if (!tick) throw new Error('No animation to be flushed'); + if(tick.method !== name) { + throw new Error('The next animation is not "' + name + + '", but is "' + tick.method + '"'); + } + tick.fn(); + return tick; + } + }; + + angular.forEach(['enter','leave','move','addClass','removeClass'], function(method) { + animate[method] = function() { + var params = arguments; + animate.queue.push({ + method : method, + params : params, + element : angular.isElement(params[0]) && params[0], + parent : angular.isElement(params[1]) && params[1], + after : angular.isElement(params[2]) && params[2], + fn : function() { + $delegate[method].apply($delegate, params); + } + }); + }; + }); + + return animate; + }); + + }]); + + +/** + * @ngdoc function + * @name angular.mock.dump + * @description + * + * *NOTE*: this is not an injectable instance, just a globally available function. + * + * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for + * debugging. + * + * This method is also available on window, where it can be used to display objects on debug + * console. + * + * @param {*} object - any object to turn into string. + * @return {string} a serialized string of the argument + */ +angular.mock.dump = function(object) { + return serialize(object); + + function serialize(object) { + var out; + + if (angular.isElement(object)) { + object = angular.element(object); + out = angular.element('
      '); + angular.forEach(object, function(element) { + out.append(angular.element(element).clone()); + }); + out = out.html(); + } else if (angular.isArray(object)) { + out = []; + angular.forEach(object, function(o) { + out.push(serialize(o)); + }); + out = '[ ' + out.join(', ') + ' ]'; + } else if (angular.isObject(object)) { + if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) { + out = serializeScope(object); + } else if (object instanceof Error) { + out = object.stack || ('' + object.name + ': ' + object.message); + } else { + // TODO(i): this prevents methods being logged, + // we should have a better way to serialize objects + out = angular.toJson(object, true); + } + } else { + out = String(object); + } + + return out; + } + + function serializeScope(scope, offset) { + offset = offset || ' '; + var log = [offset + 'Scope(' + scope.$id + '): {']; + for ( var key in scope ) { + if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) { + log.push(' ' + key + ': ' + angular.toJson(scope[key])); + } + } + var child = scope.$$childHead; + while(child) { + log.push(serializeScope(child, offset + ' ')); + child = child.$$nextSibling; + } + log.push('}'); + return log.join('\n' + offset); + } +}; + +/** + * @ngdoc object + * @name ngMock.$httpBackend + * @description + * Fake HTTP backend implementation suitable for unit testing applications that use the + * {@link ng.$http $http service}. + * + * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less + * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}. + * + * During unit testing, we want our unit tests to run quickly and have no external dependencies so + * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or + * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is + * to verify whether a certain request has been sent or not, or alternatively just let the + * application make requests, respond with pre-trained responses and assert that the end result is + * what we expect it to be. + * + * This mock implementation can be used to respond with static or dynamic responses via the + * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc). + * + * When an Angular application needs some data from a server, it calls the $http service, which + * sends the request to a real server using $httpBackend service. With dependency injection, it is + * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify + * the requests and respond with some testing data without sending a request to real server. + * + * There are two ways to specify what test data should be returned as http responses by the mock + * backend when the code under test makes http requests: + * + * - `$httpBackend.expect` - specifies a request expectation + * - `$httpBackend.when` - specifies a backend definition + * + * + * # Request Expectations vs Backend Definitions + * + * Request expectations provide a way to make assertions about requests made by the application and + * to define responses for those requests. The test will fail if the expected requests are not made + * or they are made in the wrong order. + * + * Backend definitions allow you to define a fake backend for your application which doesn't assert + * if a particular request was made or not, it just returns a trained response if a request is made. + * The test will pass whether or not the request gets made during testing. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
      Request expectationsBackend definitions
      Syntax.expect(...).respond(...).when(...).respond(...)
      Typical usagestrict unit testsloose (black-box) unit testing
      Fulfills multiple requestsNOYES
      Order of requests mattersYESNO
      Request requiredYESNO
      Response requiredoptional (see below)YES
      + * + * In cases where both backend definitions and request expectations are specified during unit + * testing, the request expectations are evaluated first. + * + * If a request expectation has no response specified, the algorithm will search your backend + * definitions for an appropriate response. + * + * If a request didn't match any expectation or if the expectation doesn't have the response + * defined, the backend definitions are evaluated in sequential order to see if any of them match + * the request. The response from the first matched definition is returned. + * + * + * # Flushing HTTP requests + * + * The $httpBackend used in production, always responds to requests with responses asynchronously. + * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are + * hard to write, follow and maintain. At the same time the testing mock, can't respond + * synchronously because that would change the execution of the code under test. For this reason the + * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending + * requests and thus preserving the async api of the backend, while allowing the test to execute + * synchronously. + * + * + * # Unit testing with mock $httpBackend + * The following code shows how to setup and use the mock backend in unit testing a controller. + * First we create the controller under test + * +
      +  // The controller code
      +  function MyController($scope, $http) {
      +    var authToken;
      +
      +    $http.get('/auth.py').success(function(data, status, headers) {
      +      authToken = headers('A-Token');
      +      $scope.user = data;
      +    });
      +
      +    $scope.saveMessage = function(message) {
      +      var headers = { 'Authorization': authToken };
      +      $scope.status = 'Saving...';
      +
      +      $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
      +        $scope.status = '';
      +      }).error(function() {
      +        $scope.status = 'ERROR!';
      +      });
      +    };
      +  }
      +  
      + * + * Now we setup the mock backend and create the test specs. + * +
      +    // testing controller
      +    describe('MyController', function() {
      +       var $httpBackend, $rootScope, createController;
      +
      +       beforeEach(inject(function($injector) {
      +         // Set up the mock http service responses
      +         $httpBackend = $injector.get('$httpBackend');
      +         // backend definition common for all tests
      +         $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
      +
      +         // Get hold of a scope (i.e. the root scope)
      +         $rootScope = $injector.get('$rootScope');
      +         // The $controller service is used to create instances of controllers
      +         var $controller = $injector.get('$controller');
      +
      +         createController = function() {
      +           return $controller('MyController', {'$scope' : $rootScope });
      +         };
      +       }));
      +
      +
      +       afterEach(function() {
      +         $httpBackend.verifyNoOutstandingExpectation();
      +         $httpBackend.verifyNoOutstandingRequest();
      +       });
      +
      +
      +       it('should fetch authentication token', function() {
      +         $httpBackend.expectGET('/auth.py');
      +         var controller = createController();
      +         $httpBackend.flush();
      +       });
      +
      +
      +       it('should send msg to server', function() {
      +         var controller = createController();
      +         $httpBackend.flush();
      +
      +         // now you don’t care about the authentication, but
      +         // the controller will still send the request and
      +         // $httpBackend will respond without you having to
      +         // specify the expectation and response for this request
      +
      +         $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
      +         $rootScope.saveMessage('message content');
      +         expect($rootScope.status).toBe('Saving...');
      +         $httpBackend.flush();
      +         expect($rootScope.status).toBe('');
      +       });
      +
      +
      +       it('should send auth header', function() {
      +         var controller = createController();
      +         $httpBackend.flush();
      +
      +         $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
      +           // check if the header was send, if it wasn't the expectation won't
      +           // match the request and the test will fail
      +           return headers['Authorization'] == 'xxx';
      +         }).respond(201, '');
      +
      +         $rootScope.saveMessage('whatever');
      +         $httpBackend.flush();
      +       });
      +    });
      +   
      + */ +angular.mock.$HttpBackendProvider = function() { + this.$get = ['$rootScope', createHttpBackendMock]; +}; + +/** + * General factory function for $httpBackend mock. + * Returns instance for unit testing (when no arguments specified): + * - passing through is disabled + * - auto flushing is disabled + * + * Returns instance for e2e testing (when `$delegate` and `$browser` specified): + * - passing through (delegating request to real backend) is enabled + * - auto flushing is enabled + * + * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified) + * @param {Object=} $browser Auto-flushing enabled if specified + * @return {Object} Instance of $httpBackend mock + */ +function createHttpBackendMock($rootScope, $delegate, $browser) { + var definitions = [], + expectations = [], + responses = [], + responsesPush = angular.bind(responses, responses.push), + copy = angular.copy; + + function createResponse(status, data, headers) { + if (angular.isFunction(status)) return status; + + return function() { + return angular.isNumber(status) + ? [status, data, headers] + : [200, status, data]; + }; + } + + // TODO(vojta): change params to: method, url, data, headers, callback + function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) { + var xhr = new MockXhr(), + expectation = expectations[0], + wasExpected = false; + + function prettyPrint(data) { + return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp) + ? data + : angular.toJson(data); + } + + function wrapResponse(wrapped) { + if (!$browser && timeout && timeout.then) timeout.then(handleTimeout); + + return handleResponse; + + function handleResponse() { + var response = wrapped.response(method, url, data, headers); + xhr.$$respHeaders = response[2]; + callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders()); + } + + function handleTimeout() { + for (var i = 0, ii = responses.length; i < ii; i++) { + if (responses[i] === handleResponse) { + responses.splice(i, 1); + callback(-1, undefined, ''); + break; + } + } + } + } + + if (expectation && expectation.match(method, url)) { + if (!expectation.matchData(data)) + throw new Error('Expected ' + expectation + ' with different data\n' + + 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data); + + if (!expectation.matchHeaders(headers)) + throw new Error('Expected ' + expectation + ' with different headers\n' + + 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + + prettyPrint(headers)); + + expectations.shift(); + + if (expectation.response) { + responses.push(wrapResponse(expectation)); + return; + } + wasExpected = true; + } + + var i = -1, definition; + while ((definition = definitions[++i])) { + if (definition.match(method, url, data, headers || {})) { + if (definition.response) { + // if $browser specified, we do auto flush all requests + ($browser ? $browser.defer : responsesPush)(wrapResponse(definition)); + } else if (definition.passThrough) { + $delegate(method, url, data, callback, headers, timeout, withCredentials); + } else throw new Error('No response defined !'); + return; + } + } + throw wasExpected ? + new Error('No response defined !') : + new Error('Unexpected request: ' + method + ' ' + url + '\n' + + (expectation ? 'Expected ' + expectation : 'No more request expected')); + } + + /** + * @ngdoc method + * @name ngMock.$httpBackend#when + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. + * + * - respond – + * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + */ + $httpBackend.when = function(method, url, data, headers) { + var definition = new MockHttpExpectation(method, url, data, headers), + chain = { + respond: function(status, data, headers) { + definition.response = createResponse(status, data, headers); + } + }; + + if ($browser) { + chain.passThrough = function() { + definition.passThrough = true; + }; + } + + definitions.push(definition); + return chain; + }; + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenGET + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for GET requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenHEAD + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for HEAD requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenDELETE + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for DELETE requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenPOST + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for POST requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenPUT + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for PUT requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenJSONP + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for JSONP requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + createShortMethods('when'); + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expect + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + * + * - respond – + * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + */ + $httpBackend.expect = function(method, url, data, headers) { + var expectation = new MockHttpExpectation(method, url, data, headers); + expectations.push(expectation); + return { + respond: function(status, data, headers) { + expectation.response = createResponse(status, data, headers); + } + }; + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectGET + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for GET requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. See #expect for more info. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectHEAD + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for HEAD requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectDELETE + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for DELETE requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectPOST + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for POST requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectPUT + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for PUT requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectPATCH + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for PATCH requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectJSONP + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for JSONP requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + createShortMethods('expect'); + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#flush + * @methodOf ngMock.$httpBackend + * @description + * Flushes all pending requests using the trained responses. + * + * @param {number=} count Number of responses to flush (in the order they arrived). If undefined, + * all pending requests will be flushed. If there are no pending requests when the flush method + * is called an exception is thrown (as this typically a sign of programming error). + */ + $httpBackend.flush = function(count) { + $rootScope.$digest(); + if (!responses.length) throw new Error('No pending request to flush !'); + + if (angular.isDefined(count)) { + while (count--) { + if (!responses.length) throw new Error('No more pending request to flush !'); + responses.shift()(); + } + } else { + while (responses.length) { + responses.shift()(); + } + } + $httpBackend.verifyNoOutstandingExpectation(); + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#verifyNoOutstandingExpectation + * @methodOf ngMock.$httpBackend + * @description + * Verifies that all of the requests defined via the `expect` api were made. If any of the + * requests were not made, verifyNoOutstandingExpectation throws an exception. + * + * Typically, you would call this method following each test case that asserts requests using an + * "afterEach" clause. + * + *
      +   *   afterEach($httpBackend.verifyNoOutstandingExpectation);
      +   * 
      + */ + $httpBackend.verifyNoOutstandingExpectation = function() { + $rootScope.$digest(); + if (expectations.length) { + throw new Error('Unsatisfied requests: ' + expectations.join(', ')); + } + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#verifyNoOutstandingRequest + * @methodOf ngMock.$httpBackend + * @description + * Verifies that there are no outstanding requests that need to be flushed. + * + * Typically, you would call this method following each test case that asserts requests using an + * "afterEach" clause. + * + *
      +   *   afterEach($httpBackend.verifyNoOutstandingRequest);
      +   * 
      + */ + $httpBackend.verifyNoOutstandingRequest = function() { + if (responses.length) { + throw new Error('Unflushed requests: ' + responses.length); + } + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#resetExpectations + * @methodOf ngMock.$httpBackend + * @description + * Resets all request expectations, but preserves all backend definitions. Typically, you would + * call resetExpectations during a multiple-phase test when you want to reuse the same instance of + * $httpBackend mock. + */ + $httpBackend.resetExpectations = function() { + expectations.length = 0; + responses.length = 0; + }; + + return $httpBackend; + + + function createShortMethods(prefix) { + angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) { + $httpBackend[prefix + method] = function(url, headers) { + return $httpBackend[prefix](method, url, undefined, headers); + }; + }); + + angular.forEach(['PUT', 'POST', 'PATCH'], function(method) { + $httpBackend[prefix + method] = function(url, data, headers) { + return $httpBackend[prefix](method, url, data, headers); + }; + }); + } +} + +function MockHttpExpectation(method, url, data, headers) { + + this.data = data; + this.headers = headers; + + this.match = function(m, u, d, h) { + if (method != m) return false; + if (!this.matchUrl(u)) return false; + if (angular.isDefined(d) && !this.matchData(d)) return false; + if (angular.isDefined(h) && !this.matchHeaders(h)) return false; + return true; + }; + + this.matchUrl = function(u) { + if (!url) return true; + if (angular.isFunction(url.test)) return url.test(u); + return url == u; + }; + + this.matchHeaders = function(h) { + if (angular.isUndefined(headers)) return true; + if (angular.isFunction(headers)) return headers(h); + return angular.equals(headers, h); + }; + + this.matchData = function(d) { + if (angular.isUndefined(data)) return true; + if (data && angular.isFunction(data.test)) return data.test(d); + if (data && angular.isFunction(data)) return data(d); + if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d)); + return data == d; + }; + + this.toString = function() { + return method + ' ' + url; + }; +} + +function createMockXhr() { + return new MockXhr(); +} + +function MockXhr() { + + // hack for testing $http, $httpBackend + MockXhr.$$lastInstance = this; + + this.open = function(method, url, async) { + this.$$method = method; + this.$$url = url; + this.$$async = async; + this.$$reqHeaders = {}; + this.$$respHeaders = {}; + }; + + this.send = function(data) { + this.$$data = data; + }; + + this.setRequestHeader = function(key, value) { + this.$$reqHeaders[key] = value; + }; + + this.getResponseHeader = function(name) { + // the lookup must be case insensitive, + // that's why we try two quick lookups first and full scan last + var header = this.$$respHeaders[name]; + if (header) return header; + + name = angular.lowercase(name); + header = this.$$respHeaders[name]; + if (header) return header; + + header = undefined; + angular.forEach(this.$$respHeaders, function(headerVal, headerName) { + if (!header && angular.lowercase(headerName) == name) header = headerVal; + }); + return header; + }; + + this.getAllResponseHeaders = function() { + var lines = []; + + angular.forEach(this.$$respHeaders, function(value, key) { + lines.push(key + ': ' + value); + }); + return lines.join('\n'); + }; + + this.abort = angular.noop; +} + + +/** + * @ngdoc function + * @name ngMock.$timeout + * @description + * + * This service is just a simple decorator for {@link ng.$timeout $timeout} service + * that adds a "flush" and "verifyNoPendingTasks" methods. + */ + +angular.mock.$TimeoutDecorator = function($delegate, $browser) { + + /** + * @ngdoc method + * @name ngMock.$timeout#flush + * @methodOf ngMock.$timeout + * @description + * + * Flushes the queue of pending tasks. + * + * @param {number=} delay maximum timeout amount to flush up until + */ + $delegate.flush = function(delay) { + $browser.defer.flush(delay); + }; + + /** + * @ngdoc method + * @name ngMock.$timeout#verifyNoPendingTasks + * @methodOf ngMock.$timeout + * @description + * + * Verifies that there are no pending tasks that need to be flushed. + */ + $delegate.verifyNoPendingTasks = function() { + if ($browser.deferredFns.length) { + throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' + + formatPendingTasksAsString($browser.deferredFns)); + } + }; + + function formatPendingTasksAsString(tasks) { + var result = []; + angular.forEach(tasks, function(task) { + result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}'); + }); + + return result.join(', '); + } + + return $delegate; +}; + +/** + * + */ +angular.mock.$RootElementProvider = function() { + this.$get = function() { + return angular.element('
      '); + }; +}; + +/** + * @ngdoc overview + * @name ngMock + * @description + * + * # ngMock + * + * The `ngMock` module providers support to inject and mock Angular services into unit tests. + * In addition, ngMock also extends various core ng services such that they can be + * inspected and controlled in a synchronous manner within test code. + * + * {@installModule mocks} + * + *
      + * + */ +angular.module('ngMock', ['ng']).provider({ + $browser: angular.mock.$BrowserProvider, + $exceptionHandler: angular.mock.$ExceptionHandlerProvider, + $log: angular.mock.$LogProvider, + $interval: angular.mock.$IntervalProvider, + $httpBackend: angular.mock.$HttpBackendProvider, + $rootElement: angular.mock.$RootElementProvider +}).config(['$provide', function($provide) { + $provide.decorator('$timeout', angular.mock.$TimeoutDecorator); +}]); + +/** + * @ngdoc overview + * @name ngMockE2E + * @description + * + * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing. + * Currently there is only one mock present in this module - + * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock. + */ +angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) { + $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); +}]); + +/** + * @ngdoc object + * @name ngMockE2E.$httpBackend + * @description + * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of + * applications that use the {@link ng.$http $http service}. + * + * *Note*: For fake http backend implementation suitable for unit testing please see + * {@link ngMock.$httpBackend unit-testing $httpBackend mock}. + * + * This implementation can be used to respond with static or dynamic responses via the `when` api + * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the + * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch + * templates from a webserver). + * + * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application + * is being developed with the real backend api replaced with a mock, it is often desirable for + * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch + * templates or static files from the webserver). To configure the backend with this behavior + * use the `passThrough` request handler of `when` instead of `respond`. + * + * Additionally, we don't want to manually have to flush mocked out requests like we do during unit + * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests + * automatically, closely simulating the behavior of the XMLHttpRequest object. + * + * To setup the application to run with this http backend, you have to create a module that depends + * on the `ngMockE2E` and your application modules and defines the fake backend: + * + *
      + *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
      + *   myAppDev.run(function($httpBackend) {
      + *     phones = [{name: 'phone1'}, {name: 'phone2'}];
      + *
      + *     // returns the current list of phones
      + *     $httpBackend.whenGET('/phones').respond(phones);
      + *
      + *     // adds a new phone to the phones array
      + *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
      + *       phones.push(angular.fromJson(data));
      + *     });
      + *     $httpBackend.whenGET(/^\/templates\//).passThrough();
      + *     //...
      + *   });
      + * 
      + * + * Afterwards, bootstrap your app with this new module. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#when + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + * + * - respond – + * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough` + * handler, will be pass through to the real backend (an XHR request will be made to the + * server. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenGET + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for GET requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenHEAD + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for HEAD requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenDELETE + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for DELETE requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenPOST + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for POST requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenPUT + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for PUT requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenPATCH + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for PATCH requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + +/** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenJSONP + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for JSONP requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ +angular.mock.e2e = {}; +angular.mock.e2e.$httpBackendDecorator = + ['$rootScope', '$delegate', '$browser', createHttpBackendMock]; + + +angular.mock.clearDataCache = function() { + var key, + cache = angular.element.cache; + + for(key in cache) { + if (Object.prototype.hasOwnProperty.call(cache,key)) { + var handle = cache[key].handle; + + handle && angular.element(handle.elem).off(); + delete cache[key]; + } + } +}; + + + +if(window.jasmine || window.mocha) { + + var currentSpec = null, + isSpecRunning = function() { + return currentSpec && (window.mocha || currentSpec.queue.running); + }; + + + beforeEach(function() { + currentSpec = this; + }); + + afterEach(function() { + var injector = currentSpec.$injector; + + currentSpec.$injector = null; + currentSpec.$modules = null; + currentSpec = null; + + if (injector) { + injector.get('$rootElement').off(); + injector.get('$browser').pollFns.length = 0; + } + + angular.mock.clearDataCache(); + + // clean up jquery's fragment cache + angular.forEach(angular.element.fragments, function(val, key) { + delete angular.element.fragments[key]; + }); + + MockXhr.$$lastInstance = null; + + angular.forEach(angular.callbacks, function(val, key) { + delete angular.callbacks[key]; + }); + angular.callbacks.counter = 0; + }); + + /** + * @ngdoc function + * @name angular.mock.module + * @description + * + * *NOTE*: This function is also published on window for easy access.
      + * + * This function registers a module configuration code. It collects the configuration information + * which will be used when the injector is created by {@link angular.mock.inject inject}. + * + * See {@link angular.mock.inject inject} for usage example + * + * @param {...(string|Function|Object)} fns any number of modules which are represented as string + * aliases or as anonymous module initialization functions. The modules are used to + * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an + * object literal is passed they will be register as values in the module, the key being + * the module name and the value being what is returned. + */ + window.module = angular.mock.module = function() { + var moduleFns = Array.prototype.slice.call(arguments, 0); + return isSpecRunning() ? workFn() : workFn; + ///////////////////// + function workFn() { + if (currentSpec.$injector) { + throw new Error('Injector already created, can not register a module!'); + } else { + var modules = currentSpec.$modules || (currentSpec.$modules = []); + angular.forEach(moduleFns, function(module) { + if (angular.isObject(module) && !angular.isArray(module)) { + modules.push(function($provide) { + angular.forEach(module, function(value, key) { + $provide.value(key, value); + }); + }); + } else { + modules.push(module); + } + }); + } + } + }; + + /** + * @ngdoc function + * @name angular.mock.inject + * @description + * + * *NOTE*: This function is also published on window for easy access.
      + * + * The inject function wraps a function into an injectable function. The inject() creates new + * instance of {@link AUTO.$injector $injector} per test, which is then used for + * resolving references. + * + * + * ## Resolving References (Underscore Wrapping) + * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this + * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable + * that is declared in the scope of the `describe()` block. Since we would, most likely, want + * the variable to have the same name of the reference we have a problem, since the parameter + * to the `inject()` function would hide the outer variable. + * + * To help with this, the injected parameters can, optionally, be enclosed with underscores. + * These are ignored by the injector when the reference name is resolved. + * + * For example, the parameter `_myService_` would be resolved as the reference `myService`. + * Since it is available in the function body as _myService_, we can then assign it to a variable + * defined in an outer scope. + * + * ``` + * // Defined out reference variable outside + * var myService; + * + * // Wrap the parameter in underscores + * beforeEach( inject( function(_myService_){ + * myService = _myService_; + * })); + * + * // Use myService in a series of tests. + * it('makes use of myService', function() { + * myService.doStuff(); + * }); + * + * ``` + * + * See also {@link angular.mock.module angular.mock.module} + * + * ## Example + * Example of what a typical jasmine tests looks like with the inject method. + *
      +   *
      +   *   angular.module('myApplicationModule', [])
      +   *       .value('mode', 'app')
      +   *       .value('version', 'v1.0.1');
      +   *
      +   *
      +   *   describe('MyApp', function() {
      +   *
      +   *     // You need to load modules that you want to test,
      +   *     // it loads only the "ng" module by default.
      +   *     beforeEach(module('myApplicationModule'));
      +   *
      +   *
      +   *     // inject() is used to inject arguments of all given functions
      +   *     it('should provide a version', inject(function(mode, version) {
      +   *       expect(version).toEqual('v1.0.1');
      +   *       expect(mode).toEqual('app');
      +   *     }));
      +   *
      +   *
      +   *     // The inject and module method can also be used inside of the it or beforeEach
      +   *     it('should override a version and test the new version is injected', function() {
      +   *       // module() takes functions or strings (module aliases)
      +   *       module(function($provide) {
      +   *         $provide.value('version', 'overridden'); // override version here
      +   *       });
      +   *
      +   *       inject(function(version) {
      +   *         expect(version).toEqual('overridden');
      +   *       });
      +   *     });
      +   *   });
      +   *
      +   * 
      + * + * @param {...Function} fns any number of functions which will be injected using the injector. + */ + + + + var ErrorAddingDeclarationLocationStack = function(e, errorForStack) { + this.message = e.message; + this.name = e.name; + if (e.line) this.line = e.line; + if (e.sourceId) this.sourceId = e.sourceId; + if (e.stack && errorForStack) + this.stack = e.stack + '\n' + errorForStack.stack; + if (e.stackArray) this.stackArray = e.stackArray; + }; + ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString; + + window.inject = angular.mock.inject = function() { + var blockFns = Array.prototype.slice.call(arguments, 0); + var errorForStack = new Error('Declaration Location'); + return isSpecRunning() ? workFn() : workFn; + ///////////////////// + function workFn() { + var modules = currentSpec.$modules || []; + + modules.unshift('ngMock'); + modules.unshift('ng'); + var injector = currentSpec.$injector; + if (!injector) { + injector = currentSpec.$injector = angular.injector(modules); + } + for(var i = 0, ii = blockFns.length; i < ii; i++) { + try { + /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */ + injector.invoke(blockFns[i] || angular.noop, this); + /* jshint +W040 */ + } catch (e) { + if (e.stack && errorForStack) { + throw new ErrorAddingDeclarationLocationStack(e, errorForStack); + } + throw e; + } finally { + errorForStack = null; + } + } + } + }; +} + + +})(window, window.angular); diff --git a/dist/bower_components/angular-mocks/bower.json b/dist/bower_components/angular-mocks/bower.json new file mode 100644 index 000000000..ab4c556a6 --- /dev/null +++ b/dist/bower_components/angular-mocks/bower.json @@ -0,0 +1,8 @@ +{ + "name": "angular-mocks", + "version": "1.2.8", + "main": "./angular-mocks.js", + "dependencies": { + "angular": "1.2.8" + } +} diff --git a/dist/bower_components/angular-resource/.bower.json b/dist/bower_components/angular-resource/.bower.json new file mode 100644 index 000000000..845dd7a6c --- /dev/null +++ b/dist/bower_components/angular-resource/.bower.json @@ -0,0 +1,18 @@ +{ + "name": "angular-resource", + "version": "1.2.16", + "main": "./angular-resource.js", + "dependencies": { + "angular": "1.2.16" + }, + "homepage": "https://github.com/angular/bower-angular-resource", + "_release": "1.2.16", + "_resolution": { + "type": "version", + "tag": "v1.2.16", + "commit": "06a1d9f570fd47b767b019881d523a3f3416ca93" + }, + "_source": "git://github.com/angular/bower-angular-resource.git", + "_target": "~1.2.8", + "_originalSource": "angular-resource" +} \ No newline at end of file diff --git a/dist/bower_components/angular-resource/README.md b/dist/bower_components/angular-resource/README.md new file mode 100644 index 000000000..c8ac81468 --- /dev/null +++ b/dist/bower_components/angular-resource/README.md @@ -0,0 +1,54 @@ +# bower-angular-resource + +This repo is for distribution on `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngResource). +Please file issues and pull requests against that repo. + +## Install + +Install with `bower`: + +```shell +bower install angular-resource +``` + +Add a ` +``` + +And add `ngResource` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngResource']); +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/api/ngResource). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist/bower_components/angular-resource/angular-resource.js b/dist/bower_components/angular-resource/angular-resource.js new file mode 100644 index 000000000..7014984c7 --- /dev/null +++ b/dist/bower_components/angular-resource/angular-resource.js @@ -0,0 +1,610 @@ +/** + * @license AngularJS v1.2.16 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +var $resourceMinErr = angular.$$minErr('$resource'); + +// Helper functions and regex to lookup a dotted path on an object +// stopping at undefined/null. The path must be composed of ASCII +// identifiers (just like $parse) +var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/; + +function isValidDottedPath(path) { + return (path != null && path !== '' && path !== 'hasOwnProperty' && + MEMBER_NAME_REGEX.test('.' + path)); +} + +function lookupDottedPath(obj, path) { + if (!isValidDottedPath(path)) { + throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path); + } + var keys = path.split('.'); + for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) { + var key = keys[i]; + obj = (obj !== null) ? obj[key] : undefined; + } + return obj; +} + +/** + * Create a shallow copy of an object and clear other fields from the destination + */ +function shallowClearAndCopy(src, dst) { + dst = dst || {}; + + angular.forEach(dst, function(value, key){ + delete dst[key]; + }); + + for (var key in src) { + if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } + } + + return dst; +} + +/** + * @ngdoc module + * @name ngResource + * @description + * + * # ngResource + * + * The `ngResource` module provides interaction support with RESTful services + * via the $resource service. + * + * + *
      + * + * See {@link ngResource.$resource `$resource`} for usage. + */ + +/** + * @ngdoc service + * @name $resource + * @requires $http + * + * @description + * A factory which creates a resource object that lets you interact with + * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. + * + * The returned resource object has action methods which provide high-level behaviors without + * the need to interact with the low level {@link ng.$http $http} service. + * + * Requires the {@link ngResource `ngResource`} module to be installed. + * + * @param {string} url A parametrized URL template with parameters prefixed by `:` as in + * `/user/:username`. If you are using a URL with a port number (e.g. + * `http://example.com:8080/api`), it will be respected. + * + * If you are using a url with a suffix, just add the suffix, like this: + * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')` + * or even `$resource('http://example.com/resource/:resource_id.:format')` + * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be + * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you + * can escape it with `/\.`. + * + * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in + * `actions` methods. If any of the parameter value is a function, it will be executed every time + * when a param value needs to be obtained for a request (unless the param was overridden). + * + * Each key value in the parameter object is first bound to url template if present and then any + * excess keys are appended to the url search query after the `?`. + * + * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in + * URL `/path/greet?salutation=Hello`. + * + * If the parameter value is prefixed with `@` then the value of that parameter is extracted from + * the data object (useful for non-GET operations). + * + * @param {Object.=} actions Hash with declaration of custom action that should extend + * the default set of resource actions. The declaration should be created in the format of {@link + * ng.$http#usage_parameters $http.config}: + * + * {action1: {method:?, params:?, isArray:?, headers:?, ...}, + * action2: {method:?, params:?, isArray:?, headers:?, ...}, + * ...} + * + * Where: + * + * - **`action`** – {string} – The name of action. This name becomes the name of the method on + * your resource object. + * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, + * `DELETE`, and `JSONP`. + * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of + * the parameter value is a function, it will be executed every time when a param value needs to + * be obtained for a request (unless the param was overridden). + * - **`url`** – {string} – action specific `url` override. The url templating is supported just + * like for the resource-level urls. + * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, + * see `returns` section. + * - **`transformRequest`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * - **`transformResponse`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * response body and headers and returns its transformed (typically deserialized) version. + * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the + * GET request, otherwise if a cache instance built with + * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for + * caching. + * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that + * should abort the request when resolved. + * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the + * XHR object. See + * [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5) + * for more information. + * - **`responseType`** - `{string}` - see + * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType). + * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods - + * `response` and `responseError`. Both `response` and `responseError` interceptors get called + * with `http response` object. See {@link ng.$http $http interceptors}. + * + * @returns {Object} A resource "class" object with methods for the default set of resource actions + * optionally extended with custom `actions`. The default set contains these actions: + * ```js + * { 'get': {method:'GET'}, + * 'save': {method:'POST'}, + * 'query': {method:'GET', isArray:true}, + * 'remove': {method:'DELETE'}, + * 'delete': {method:'DELETE'} }; + * ``` + * + * Calling these methods invoke an {@link ng.$http} with the specified http method, + * destination and parameters. When the data is returned from the server then the object is an + * instance of the resource class. The actions `save`, `remove` and `delete` are available on it + * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create, + * read, update, delete) on server-side data like this: + * ```js + * var User = $resource('/user/:userId', {userId:'@id'}); + * var user = User.get({userId:123}, function() { + * user.abc = true; + * user.$save(); + * }); + * ``` + * + * It is important to realize that invoking a $resource object method immediately returns an + * empty reference (object or array depending on `isArray`). Once the data is returned from the + * server the existing reference is populated with the actual data. This is a useful trick since + * usually the resource is assigned to a model which is then rendered by the view. Having an empty + * object results in no rendering, once the data arrives from the server then the object is + * populated with the data and the view automatically re-renders itself showing the new data. This + * means that in most cases one never has to write a callback function for the action methods. + * + * The action methods on the class object or instance object can be invoked with the following + * parameters: + * + * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])` + * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` + * - non-GET instance actions: `instance.$action([parameters], [success], [error])` + * + * Success callback is called with (value, responseHeaders) arguments. Error callback is called + * with (httpResponse) argument. + * + * Class actions return empty instance (with additional properties below). + * Instance actions return promise of the action. + * + * The Resource instances and collection have these additional properties: + * + * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this + * instance or collection. + * + * On success, the promise is resolved with the same resource instance or collection object, + * updated with data from server. This makes it easy to use in + * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view + * rendering until the resource(s) are loaded. + * + * On failure, the promise is resolved with the {@link ng.$http http response} object, without + * the `resource` property. + * + * If an interceptor object was provided, the promise will instead be resolved with the value + * returned by the interceptor. + * + * - `$resolved`: `true` after first server interaction is completed (either with success or + * rejection), `false` before that. Knowing if the Resource has been resolved is useful in + * data-binding. + * + * @example + * + * # Credit card resource + * + * ```js + // Define CreditCard class + var CreditCard = $resource('/user/:userId/card/:cardId', + {userId:123, cardId:'@id'}, { + charge: {method:'POST', params:{charge:true}} + }); + + // We can retrieve a collection from the server + var cards = CreditCard.query(function() { + // GET: /user/123/card + // server returns: [ {id:456, number:'1234', name:'Smith'} ]; + + var card = cards[0]; + // each item is an instance of CreditCard + expect(card instanceof CreditCard).toEqual(true); + card.name = "J. Smith"; + // non GET methods are mapped onto the instances + card.$save(); + // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'} + // server returns: {id:456, number:'1234', name: 'J. Smith'}; + + // our custom method is mapped as well. + card.$charge({amount:9.99}); + // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'} + }); + + // we can create an instance as well + var newCard = new CreditCard({number:'0123'}); + newCard.name = "Mike Smith"; + newCard.$save(); + // POST: /user/123/card {number:'0123', name:'Mike Smith'} + // server returns: {id:789, number:'0123', name: 'Mike Smith'}; + expect(newCard.id).toEqual(789); + * ``` + * + * The object returned from this function execution is a resource "class" which has "static" method + * for each action in the definition. + * + * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and + * `headers`. + * When the data is returned from the server then the object is an instance of the resource type and + * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD + * operations (create, read, update, delete) on server-side data. + + ```js + var User = $resource('/user/:userId', {userId:'@id'}); + User.get({userId:123}, function(user) { + user.abc = true; + user.$save(); + }); + ``` + * + * It's worth noting that the success callback for `get`, `query` and other methods gets passed + * in the response that came from the server as well as $http header getter function, so one + * could rewrite the above example and get access to http headers as: + * + ```js + var User = $resource('/user/:userId', {userId:'@id'}); + User.get({userId:123}, function(u, getResponseHeaders){ + u.abc = true; + u.$save(function(u, putResponseHeaders) { + //u => saved user object + //putResponseHeaders => $http header getter + }); + }); + ``` + * + * You can also access the raw `$http` promise via the `$promise` property on the object returned + * + ``` + var User = $resource('/user/:userId', {userId:'@id'}); + User.get({userId:123}) + .$promise.then(function(user) { + $scope.user = user; + }); + ``` + + * # Creating a custom 'PUT' request + * In this example we create a custom method on our resource to make a PUT request + * ```js + * var app = angular.module('app', ['ngResource', 'ngRoute']); + * + * // Some APIs expect a PUT request in the format URL/object/ID + * // Here we are creating an 'update' method + * app.factory('Notes', ['$resource', function($resource) { + * return $resource('/notes/:id', null, + * { + * 'update': { method:'PUT' } + * }); + * }]); + * + * // In our controller we get the ID from the URL using ngRoute and $routeParams + * // We pass in $routeParams and our Notes factory along with $scope + * app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes', + function($scope, $routeParams, Notes) { + * // First get a note object from the factory + * var note = Notes.get({ id:$routeParams.id }); + * $id = note.id; + * + * // Now call update passing in the ID first then the object you are updating + * Notes.update({ id:$id }, note); + * + * // This will PUT /notes/ID with the note object in the request payload + * }]); + * ``` + */ +angular.module('ngResource', ['ng']). + factory('$resource', ['$http', '$q', function($http, $q) { + + var DEFAULT_ACTIONS = { + 'get': {method:'GET'}, + 'save': {method:'POST'}, + 'query': {method:'GET', isArray:true}, + 'remove': {method:'DELETE'}, + 'delete': {method:'DELETE'} + }; + var noop = angular.noop, + forEach = angular.forEach, + extend = angular.extend, + copy = angular.copy, + isFunction = angular.isFunction; + + /** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path + * segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); + } + + + /** + * This method is intended for encoding *key* or *value* parts of query component. We need a + * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't + * have to be encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); + } + + function Route(template, defaults) { + this.template = template; + this.defaults = defaults || {}; + this.urlParams = {}; + } + + Route.prototype = { + setUrlParams: function(config, params, actionUrl) { + var self = this, + url = actionUrl || self.template, + val, + encodedVal; + + var urlParams = self.urlParams = {}; + forEach(url.split(/\W/), function(param){ + if (param === 'hasOwnProperty') { + throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); + } + if (!(new RegExp("^\\d+$").test(param)) && param && + (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { + urlParams[param] = true; + } + }); + url = url.replace(/\\:/g, ':'); + + params = params || {}; + forEach(self.urlParams, function(_, urlParam){ + val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; + if (angular.isDefined(val) && val !== null) { + encodedVal = encodeUriSegment(val); + url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) { + return encodedVal + p1; + }); + } else { + url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, + leadingSlashes, tail) { + if (tail.charAt(0) == '/') { + return tail; + } else { + return leadingSlashes + tail; + } + }); + } + }); + + // strip trailing slashes and set the url + url = url.replace(/\/+$/, '') || '/'; + // then replace collapse `/.` if found in the last URL path segment before the query + // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` + url = url.replace(/\/\.(?=\w+($|\?))/, '.'); + // replace escaped `/\.` with `/.` + config.url = url.replace(/\/\\\./, '/.'); + + + // set params - delegate param encoding to $http + forEach(params, function(value, key){ + if (!self.urlParams[key]) { + config.params = config.params || {}; + config.params[key] = value; + } + }); + } + }; + + + function resourceFactory(url, paramDefaults, actions) { + var route = new Route(url); + + actions = extend({}, DEFAULT_ACTIONS, actions); + + function extractParams(data, actionParams){ + var ids = {}; + actionParams = extend({}, paramDefaults, actionParams); + forEach(actionParams, function(value, key){ + if (isFunction(value)) { value = value(); } + ids[key] = value && value.charAt && value.charAt(0) == '@' ? + lookupDottedPath(data, value.substr(1)) : value; + }); + return ids; + } + + function defaultResponseInterceptor(response) { + return response.resource; + } + + function Resource(value){ + shallowClearAndCopy(value || {}, this); + } + + forEach(actions, function(action, name) { + var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); + + Resource[name] = function(a1, a2, a3, a4) { + var params = {}, data, success, error; + + /* jshint -W086 */ /* (purposefully fall through case statements) */ + switch(arguments.length) { + case 4: + error = a4; + success = a3; + //fallthrough + case 3: + case 2: + if (isFunction(a2)) { + if (isFunction(a1)) { + success = a1; + error = a2; + break; + } + + success = a2; + error = a3; + //fallthrough + } else { + params = a1; + data = a2; + success = a3; + break; + } + case 1: + if (isFunction(a1)) success = a1; + else if (hasBody) data = a1; + else params = a1; + break; + case 0: break; + default: + throw $resourceMinErr('badargs', + "Expected up to 4 arguments [params, data, success, error], got {0} arguments", + arguments.length); + } + /* jshint +W086 */ /* (purposefully fall through case statements) */ + + var isInstanceCall = this instanceof Resource; + var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); + var httpConfig = {}; + var responseInterceptor = action.interceptor && action.interceptor.response || + defaultResponseInterceptor; + var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || + undefined; + + forEach(action, function(value, key) { + if (key != 'params' && key != 'isArray' && key != 'interceptor') { + httpConfig[key] = copy(value); + } + }); + + if (hasBody) httpConfig.data = data; + route.setUrlParams(httpConfig, + extend({}, extractParams(data, action.params || {}), params), + action.url); + + var promise = $http(httpConfig).then(function(response) { + var data = response.data, + promise = value.$promise; + + if (data) { + // Need to convert action.isArray to boolean in case it is undefined + // jshint -W018 + if (angular.isArray(data) !== (!!action.isArray)) { + throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' + + 'response to contain an {0} but got an {1}', + action.isArray?'array':'object', angular.isArray(data)?'array':'object'); + } + // jshint +W018 + if (action.isArray) { + value.length = 0; + forEach(data, function(item) { + value.push(new Resource(item)); + }); + } else { + shallowClearAndCopy(data, value); + value.$promise = promise; + } + } + + value.$resolved = true; + + response.resource = value; + + return response; + }, function(response) { + value.$resolved = true; + + (error||noop)(response); + + return $q.reject(response); + }); + + promise = promise.then( + function(response) { + var value = responseInterceptor(response); + (success||noop)(value, response.headers); + return value; + }, + responseErrorInterceptor); + + if (!isInstanceCall) { + // we are creating instance / collection + // - set the initial promise + // - return the instance / collection + value.$promise = promise; + value.$resolved = false; + + return value; + } + + // instance call + return promise; + }; + + + Resource.prototype['$' + name] = function(params, success, error) { + if (isFunction(params)) { + error = success; success = params; params = {}; + } + var result = Resource[name].call(this, params, this, success, error); + return result.$promise || result; + }; + }); + + Resource.bind = function(additionalParamDefaults){ + return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); + }; + + return Resource; + } + + return resourceFactory; + }]); + + +})(window, window.angular); diff --git a/dist/bower_components/angular-resource/angular-resource.min.js b/dist/bower_components/angular-resource/angular-resource.min.js new file mode 100644 index 000000000..eac389ed1 --- /dev/null +++ b/dist/bower_components/angular-resource/angular-resource.min.js @@ -0,0 +1,13 @@ +/* + AngularJS v1.2.16 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(H,a,A){'use strict';function D(p,g){g=g||{};a.forEach(g,function(a,c){delete g[c]});for(var c in p)!p.hasOwnProperty(c)||"$"===c.charAt(0)&&"$"===c.charAt(1)||(g[c]=p[c]);return g}var v=a.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;a.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(p,g){function c(a,c){this.template=a;this.defaults=c||{};this.urlParams={}}function t(n,w,l){function r(h,d){var e={};d=x({},w,d);s(d,function(b,d){u(b)&&(b=b());var k;if(b&& +b.charAt&&"@"==b.charAt(0)){k=h;var a=b.substr(1);if(null==a||""===a||"hasOwnProperty"===a||!C.test("."+a))throw v("badmember",a);for(var a=a.split("."),f=0,c=a.length;f` to your `index.html`: + +```html + +``` + +And add `ngRoute` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngRoute']); +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/api/ngRoute). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist/bower_components/angular-route/angular-route.js b/dist/bower_components/angular-route/angular-route.js new file mode 100644 index 000000000..f7ebda8bb --- /dev/null +++ b/dist/bower_components/angular-route/angular-route.js @@ -0,0 +1,927 @@ +/** + * @license AngularJS v1.2.16 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +/** + * @ngdoc module + * @name ngRoute + * @description + * + * # ngRoute + * + * The `ngRoute` module provides routing and deeplinking services and directives for angular apps. + * + * ## Example + * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. + * + * + *
      + */ + /* global -ngRouteModule */ +var ngRouteModule = angular.module('ngRoute', ['ng']). + provider('$route', $RouteProvider); + +/** + * @ngdoc provider + * @name $routeProvider + * @function + * + * @description + * + * Used for configuring routes. + * + * ## Example + * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. + * + * ## Dependencies + * Requires the {@link ngRoute `ngRoute`} module to be installed. + */ +function $RouteProvider(){ + function inherit(parent, extra) { + return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra); + } + + var routes = {}; + + /** + * @ngdoc method + * @name $routeProvider#when + * + * @param {string} path Route path (matched against `$location.path`). If `$location.path` + * contains redundant trailing slash or is missing one, the route will still match and the + * `$location.path` will be updated to add or drop the trailing slash to exactly match the + * route definition. + * + * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up + * to the next slash are matched and stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain named groups starting with a colon and ending with a star: + * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain optional named groups with a question mark: e.g.`:name?`. + * + * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match + * `/color/brown/largecode/code/with/slashes/edit` and extract: + * + * * `color: brown` + * * `largecode: code/with/slashes`. + * + * + * @param {Object} route Mapping information to be assigned to `$route.current` on route + * match. + * + * Object properties: + * + * - `controller` – `{(string|function()=}` – Controller fn that should be associated with + * newly created scope or the name of a {@link angular.Module#controller registered + * controller} if passed as a string. + * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be + * published to scope under the `controllerAs` name. + * - `template` – `{string=|function()=}` – html template as a string or a function that + * returns an html template as a string which should be used by {@link + * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives. + * This property takes precedence over `templateUrl`. + * + * If `template` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html + * template that should be used by {@link ngRoute.directive:ngView ngView}. + * + * If `templateUrl` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `resolve` - `{Object.=}` - An optional map of dependencies which should + * be injected into the controller. If any of these dependencies are promises, the router + * will wait for them all to be resolved or one to be rejected before the controller is + * instantiated. + * If all the promises are resolved successfully, the values of the resolved promises are + * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is + * fired. If any of the promises are rejected the + * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object + * is: + * + * - `key` – `{string}`: a name of a dependency to be injected into the controller. + * - `factory` - `{string|function}`: If `string` then it is an alias for a service. + * Otherwise if function, then it is {@link auto.$injector#invoke injected} + * and the return value is treated as the dependency. If the result is a promise, it is + * resolved before its value is injected into the controller. Be aware that + * `ngRoute.$routeParams` will still refer to the previous route within these resolve + * functions. Use `$route.current.params` to access the new route parameters, instead. + * + * - `redirectTo` – {(string|function())=} – value to update + * {@link ng.$location $location} path with and trigger route redirection. + * + * If `redirectTo` is a function, it will be called with the following parameters: + * + * - `{Object.}` - route parameters extracted from the current + * `$location.path()` by applying the current route templateUrl. + * - `{string}` - current `$location.path()` + * - `{Object}` - current `$location.search()` + * + * The custom `redirectTo` function is expected to return a string which will be used + * to update `$location.path()` and `$location.search()`. + * + * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()` + * or `$location.hash()` changes. + * + * If the option is set to `false` and url in the browser changes, then + * `$routeUpdate` event is broadcasted on the root scope. + * + * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive + * + * If the option is set to `true`, then the particular route can be matched without being + * case sensitive + * + * @returns {Object} self + * + * @description + * Adds a new route definition to the `$route` service. + */ + this.when = function(path, route) { + routes[path] = angular.extend( + {reloadOnSearch: true}, + route, + path && pathRegExp(path, route) + ); + + // create redirection for trailing slashes + if (path) { + var redirectPath = (path[path.length-1] == '/') + ? path.substr(0, path.length-1) + : path +'/'; + + routes[redirectPath] = angular.extend( + {redirectTo: path}, + pathRegExp(redirectPath, route) + ); + } + + return this; + }; + + /** + * @param path {string} path + * @param opts {Object} options + * @return {?Object} + * + * @description + * Normalizes the given path, returning a regular expression + * and the original path. + * + * Inspired by pathRexp in visionmedia/express/lib/utils.js. + */ + function pathRegExp(path, opts) { + var insensitive = opts.caseInsensitiveMatch, + ret = { + originalPath: path, + regexp: path + }, + keys = ret.keys = []; + + path = path + .replace(/([().])/g, '\\$1') + .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option){ + var optional = option === '?' ? option : null; + var star = option === '*' ? option : null; + keys.push({ name: key, optional: !!optional }); + slash = slash || ''; + return '' + + (optional ? '' : slash) + + '(?:' + + (optional ? slash : '') + + (star && '(.+?)' || '([^/]+)') + + (optional || '') + + ')' + + (optional || ''); + }) + .replace(/([\/$\*])/g, '\\$1'); + + ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : ''); + return ret; + } + + /** + * @ngdoc method + * @name $routeProvider#otherwise + * + * @description + * Sets route definition that will be used on route change when no other route definition + * is matched. + * + * @param {Object} params Mapping information to be assigned to `$route.current`. + * @returns {Object} self + */ + this.otherwise = function(params) { + this.when(null, params); + return this; + }; + + + this.$get = ['$rootScope', + '$location', + '$routeParams', + '$q', + '$injector', + '$http', + '$templateCache', + '$sce', + function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) { + + /** + * @ngdoc service + * @name $route + * @requires $location + * @requires $routeParams + * + * @property {Object} current Reference to the current route definition. + * The route definition contains: + * + * - `controller`: The controller constructor as define in route definition. + * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for + * controller instantiation. The `locals` contain + * the resolved values of the `resolve` map. Additionally the `locals` also contain: + * + * - `$scope` - The current route scope. + * - `$template` - The current route template HTML. + * + * @property {Object} routes Object with all route configuration Objects as its properties. + * + * @description + * `$route` is used for deep-linking URLs to controllers and views (HTML partials). + * It watches `$location.url()` and tries to map the path to an existing route definition. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API. + * + * The `$route` service is typically used in conjunction with the + * {@link ngRoute.directive:ngView `ngView`} directive and the + * {@link ngRoute.$routeParams `$routeParams`} service. + * + * @example + * This example shows how changing the URL hash causes the `$route` to match a route against the + * URL, and the `ngView` pulls in the partial. + * + * Note that this example is using {@link ng.directive:script inlined templates} + * to get it working on jsfiddle as well. + * + * + * + *
      + * Choose: + * Moby | + * Moby: Ch1 | + * Gatsby | + * Gatsby: Ch4 | + * Scarlet Letter
      + * + *
      + * + *
      + * + *
      $location.path() = {{$location.path()}}
      + *
      $route.current.templateUrl = {{$route.current.templateUrl}}
      + *
      $route.current.params = {{$route.current.params}}
      + *
      $route.current.scope.name = {{$route.current.scope.name}}
      + *
      $routeParams = {{$routeParams}}
      + *
      + *
      + * + * + * controller: {{name}}
      + * Book Id: {{params.bookId}}
      + *
      + * + * + * controller: {{name}}
      + * Book Id: {{params.bookId}}
      + * Chapter Id: {{params.chapterId}} + *
      + * + * + * angular.module('ngRouteExample', ['ngRoute']) + * + * .controller('MainController', function($scope, $route, $routeParams, $location) { + * $scope.$route = $route; + * $scope.$location = $location; + * $scope.$routeParams = $routeParams; + * }) + * + * .controller('BookController', function($scope, $routeParams) { + * $scope.name = "BookController"; + * $scope.params = $routeParams; + * }) + * + * .controller('ChapterController', function($scope, $routeParams) { + * $scope.name = "ChapterController"; + * $scope.params = $routeParams; + * }) + * + * .config(function($routeProvider, $locationProvider) { + * $routeProvider + * .when('/Book/:bookId', { + * templateUrl: 'book.html', + * controller: 'BookController', + * resolve: { + * // I will cause a 1 second delay + * delay: function($q, $timeout) { + * var delay = $q.defer(); + * $timeout(delay.resolve, 1000); + * return delay.promise; + * } + * } + * }) + * .when('/Book/:bookId/ch/:chapterId', { + * templateUrl: 'chapter.html', + * controller: 'ChapterController' + * }); + * + * // configure html5 to get links working on jsfiddle + * $locationProvider.html5Mode(true); + * }); + * + * + * + * + * it('should load and compile correct template', function() { + * element(by.linkText('Moby: Ch1')).click(); + * var content = element(by.css('[ng-view]')).getText(); + * expect(content).toMatch(/controller\: ChapterController/); + * expect(content).toMatch(/Book Id\: Moby/); + * expect(content).toMatch(/Chapter Id\: 1/); + * + * element(by.partialLinkText('Scarlet')).click(); + * + * content = element(by.css('[ng-view]')).getText(); + * expect(content).toMatch(/controller\: BookController/); + * expect(content).toMatch(/Book Id\: Scarlet/); + * }); + * + *
      + */ + + /** + * @ngdoc event + * @name $route#$routeChangeStart + * @eventType broadcast on root scope + * @description + * Broadcasted before a route change. At this point the route services starts + * resolving all of the dependencies needed for the route change to occur. + * Typically this involves fetching the view template as well as any dependencies + * defined in `resolve` route property. Once all of the dependencies are resolved + * `$routeChangeSuccess` is fired. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} next Future route information. + * @param {Route} current Current route information. + */ + + /** + * @ngdoc event + * @name $route#$routeChangeSuccess + * @eventType broadcast on root scope + * @description + * Broadcasted after a route dependencies are resolved. + * {@link ngRoute.directive:ngView ngView} listens for the directive + * to instantiate the controller and render the view. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} current Current route information. + * @param {Route|Undefined} previous Previous route information, or undefined if current is + * first route entered. + */ + + /** + * @ngdoc event + * @name $route#$routeChangeError + * @eventType broadcast on root scope + * @description + * Broadcasted if any of the resolve promises are rejected. + * + * @param {Object} angularEvent Synthetic event object + * @param {Route} current Current route information. + * @param {Route} previous Previous route information. + * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. + */ + + /** + * @ngdoc event + * @name $route#$routeUpdate + * @eventType broadcast on root scope + * @description + * + * The `reloadOnSearch` property has been set to false, and we are reusing the same + * instance of the Controller. + */ + + var forceReload = false, + $route = { + routes: routes, + + /** + * @ngdoc method + * @name $route#reload + * + * @description + * Causes `$route` service to reload the current route even if + * {@link ng.$location $location} hasn't changed. + * + * As a result of that, {@link ngRoute.directive:ngView ngView} + * creates new scope, reinstantiates the controller. + */ + reload: function() { + forceReload = true; + $rootScope.$evalAsync(updateRoute); + } + }; + + $rootScope.$on('$locationChangeSuccess', updateRoute); + + return $route; + + ///////////////////////////////////////////////////// + + /** + * @param on {string} current url + * @param route {Object} route regexp to match the url against + * @return {?Object} + * + * @description + * Check if the route matches the current url. + * + * Inspired by match in + * visionmedia/express/lib/router/router.js. + */ + function switchRouteMatcher(on, route) { + var keys = route.keys, + params = {}; + + if (!route.regexp) return null; + + var m = route.regexp.exec(on); + if (!m) return null; + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + + var val = 'string' == typeof m[i] + ? decodeURIComponent(m[i]) + : m[i]; + + if (key && val) { + params[key.name] = val; + } + } + return params; + } + + function updateRoute() { + var next = parseRoute(), + last = $route.current; + + if (next && last && next.$$route === last.$$route + && angular.equals(next.pathParams, last.pathParams) + && !next.reloadOnSearch && !forceReload) { + last.params = next.params; + angular.copy(last.params, $routeParams); + $rootScope.$broadcast('$routeUpdate', last); + } else if (next || last) { + forceReload = false; + $rootScope.$broadcast('$routeChangeStart', next, last); + $route.current = next; + if (next) { + if (next.redirectTo) { + if (angular.isString(next.redirectTo)) { + $location.path(interpolate(next.redirectTo, next.params)).search(next.params) + .replace(); + } else { + $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search())) + .replace(); + } + } + } + + $q.when(next). + then(function() { + if (next) { + var locals = angular.extend({}, next.resolve), + template, templateUrl; + + angular.forEach(locals, function(value, key) { + locals[key] = angular.isString(value) ? + $injector.get(value) : $injector.invoke(value); + }); + + if (angular.isDefined(template = next.template)) { + if (angular.isFunction(template)) { + template = template(next.params); + } + } else if (angular.isDefined(templateUrl = next.templateUrl)) { + if (angular.isFunction(templateUrl)) { + templateUrl = templateUrl(next.params); + } + templateUrl = $sce.getTrustedResourceUrl(templateUrl); + if (angular.isDefined(templateUrl)) { + next.loadedTemplateUrl = templateUrl; + template = $http.get(templateUrl, {cache: $templateCache}). + then(function(response) { return response.data; }); + } + } + if (angular.isDefined(template)) { + locals['$template'] = template; + } + return $q.all(locals); + } + }). + // after route change + then(function(locals) { + if (next == $route.current) { + if (next) { + next.locals = locals; + angular.copy(next.params, $routeParams); + } + $rootScope.$broadcast('$routeChangeSuccess', next, last); + } + }, function(error) { + if (next == $route.current) { + $rootScope.$broadcast('$routeChangeError', next, last, error); + } + }); + } + } + + + /** + * @returns {Object} the current active route, by matching it against the URL + */ + function parseRoute() { + // Match a route + var params, match; + angular.forEach(routes, function(route, path) { + if (!match && (params = switchRouteMatcher($location.path(), route))) { + match = inherit(route, { + params: angular.extend({}, $location.search(), params), + pathParams: params}); + match.$$route = route; + } + }); + // No route matched; fallback to "otherwise" route + return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); + } + + /** + * @returns {string} interpolation of the redirect path with the parameters + */ + function interpolate(string, params) { + var result = []; + angular.forEach((string||'').split(':'), function(segment, i) { + if (i === 0) { + result.push(segment); + } else { + var segmentMatch = segment.match(/(\w+)(.*)/); + var key = segmentMatch[1]; + result.push(params[key]); + result.push(segmentMatch[2] || ''); + delete params[key]; + } + }); + return result.join(''); + } + }]; +} + +ngRouteModule.provider('$routeParams', $RouteParamsProvider); + + +/** + * @ngdoc service + * @name $routeParams + * @requires $route + * + * @description + * The `$routeParams` service allows you to retrieve the current set of route parameters. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * The route parameters are a combination of {@link ng.$location `$location`}'s + * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}. + * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched. + * + * In case of parameter name collision, `path` params take precedence over `search` params. + * + * The service guarantees that the identity of the `$routeParams` object will remain unchanged + * (but its properties will likely change) even when a route change occurs. + * + * Note that the `$routeParams` are only updated *after* a route change completes successfully. + * This means that you cannot rely on `$routeParams` being correct in route resolve functions. + * Instead you can use `$route.current.params` to access the new route's parameters. + * + * @example + * ```js + * // Given: + * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby + * // Route: /Chapter/:chapterId/Section/:sectionId + * // + * // Then + * $routeParams ==> {chapterId:1, sectionId:2, search:'moby'} + * ``` + */ +function $RouteParamsProvider() { + this.$get = function() { return {}; }; +} + +ngRouteModule.directive('ngView', ngViewFactory); +ngRouteModule.directive('ngView', ngViewFillContentFactory); + + +/** + * @ngdoc directive + * @name ngView + * @restrict ECA + * + * @description + * # Overview + * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by + * including the rendered template of the current route into the main layout (`index.html`) file. + * Every time the current route changes, the included view changes with it according to the + * configuration of the `$route` service. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * @animations + * enter - animation is used to bring new content into the browser. + * leave - animation is used to animate existing content away. + * + * The enter and leave animation occur concurrently. + * + * @scope + * @priority 400 + * @param {string=} onload Expression to evaluate whenever the view updates. + * + * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll + * $anchorScroll} to scroll the viewport after the view is updated. + * + * - If the attribute is not set, disable scrolling. + * - If the attribute is set without value, enable scrolling. + * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated + * as an expression yields a truthy value. + * @example + + +
      + Choose: + Moby | + Moby: Ch1 | + Gatsby | + Gatsby: Ch4 | + Scarlet Letter
      + +
      +
      +
      +
      + +
      $location.path() = {{main.$location.path()}}
      +
      $route.current.templateUrl = {{main.$route.current.templateUrl}}
      +
      $route.current.params = {{main.$route.current.params}}
      +
      $route.current.scope.name = {{main.$route.current.scope.name}}
      +
      $routeParams = {{main.$routeParams}}
      +
      +
      + + +
      + controller: {{book.name}}
      + Book Id: {{book.params.bookId}}
      +
      +
      + + +
      + controller: {{chapter.name}}
      + Book Id: {{chapter.params.bookId}}
      + Chapter Id: {{chapter.params.chapterId}} +
      +
      + + + .view-animate-container { + position:relative; + height:100px!important; + position:relative; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; + } + + .view-animate { + padding:10px; + } + + .view-animate.ng-enter, .view-animate.ng-leave { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; + + display:block; + width:100%; + border-left:1px solid black; + + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + padding:10px; + } + + .view-animate.ng-enter { + left:100%; + } + .view-animate.ng-enter.ng-enter-active { + left:0; + } + .view-animate.ng-leave.ng-leave-active { + left:-100%; + } + + + + angular.module('ngViewExample', ['ngRoute', 'ngAnimate']) + .config(['$routeProvider', '$locationProvider', + function($routeProvider, $locationProvider) { + $routeProvider + .when('/Book/:bookId', { + templateUrl: 'book.html', + controller: 'BookCtrl', + controllerAs: 'book' + }) + .when('/Book/:bookId/ch/:chapterId', { + templateUrl: 'chapter.html', + controller: 'ChapterCtrl', + controllerAs: 'chapter' + }); + + // configure html5 to get links working on jsfiddle + $locationProvider.html5Mode(true); + }]) + .controller('MainCtrl', ['$route', '$routeParams', '$location', + function($route, $routeParams, $location) { + this.$route = $route; + this.$location = $location; + this.$routeParams = $routeParams; + }]) + .controller('BookCtrl', ['$routeParams', function($routeParams) { + this.name = "BookCtrl"; + this.params = $routeParams; + }]) + .controller('ChapterCtrl', ['$routeParams', function($routeParams) { + this.name = "ChapterCtrl"; + this.params = $routeParams; + }]); + + + + + it('should load and compile correct template', function() { + element(by.linkText('Moby: Ch1')).click(); + var content = element(by.css('[ng-view]')).getText(); + expect(content).toMatch(/controller\: ChapterCtrl/); + expect(content).toMatch(/Book Id\: Moby/); + expect(content).toMatch(/Chapter Id\: 1/); + + element(by.partialLinkText('Scarlet')).click(); + + content = element(by.css('[ng-view]')).getText(); + expect(content).toMatch(/controller\: BookCtrl/); + expect(content).toMatch(/Book Id\: Scarlet/); + }); + +
      + */ + + +/** + * @ngdoc event + * @name ngView#$viewContentLoaded + * @eventType emit on the current ngView scope + * @description + * Emitted every time the ngView content is reloaded. + */ +ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate']; +function ngViewFactory( $route, $anchorScroll, $animate) { + return { + restrict: 'ECA', + terminal: true, + priority: 400, + transclude: 'element', + link: function(scope, $element, attr, ctrl, $transclude) { + var currentScope, + currentElement, + previousElement, + autoScrollExp = attr.autoscroll, + onloadExp = attr.onload || ''; + + scope.$on('$routeChangeSuccess', update); + update(); + + function cleanupLastView() { + if(previousElement) { + previousElement.remove(); + previousElement = null; + } + if(currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if(currentElement) { + $animate.leave(currentElement, function() { + previousElement = null; + }); + previousElement = currentElement; + currentElement = null; + } + } + + function update() { + var locals = $route.current && $route.current.locals, + template = locals && locals.$template; + + if (angular.isDefined(template)) { + var newScope = scope.$new(); + var current = $route.current; + + // Note: This will also link all children of ng-view that were contained in the original + // html. If that content contains controllers, ... they could pollute/change the scope. + // However, using ng-view on an element with additional content does not make sense... + // Note: We can't remove them in the cloneAttchFn of $transclude as that + // function is called before linking the content, which would apply child + // directives to non existing elements. + var clone = $transclude(newScope, function(clone) { + $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () { + if (angular.isDefined(autoScrollExp) + && (!autoScrollExp || scope.$eval(autoScrollExp))) { + $anchorScroll(); + } + }); + cleanupLastView(); + }); + + currentElement = clone; + currentScope = current.scope = newScope; + currentScope.$emit('$viewContentLoaded'); + currentScope.$eval(onloadExp); + } else { + cleanupLastView(); + } + } + } + }; +} + +// This directive is called during the $transclude call of the first `ngView` directive. +// It will replace and compile the content of the element with the loaded template. +// We need this directive so that the element content is already filled when +// the link function of another directive on the same element as ngView +// is called. +ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route']; +function ngViewFillContentFactory($compile, $controller, $route) { + return { + restrict: 'ECA', + priority: -400, + link: function(scope, $element) { + var current = $route.current, + locals = current.locals; + + $element.html(locals.$template); + + var link = $compile($element.contents()); + + if (current.controller) { + locals.$scope = scope; + var controller = $controller(current.controller, locals); + if (current.controllerAs) { + scope[current.controllerAs] = controller; + } + $element.data('$ngControllerController', controller); + $element.children().data('$ngControllerController', controller); + } + + link(scope); + } + }; +} + + +})(window, window.angular); diff --git a/dist/bower_components/angular-route/angular-route.min.js b/dist/bower_components/angular-route/angular-route.min.js new file mode 100644 index 000000000..aef1fd601 --- /dev/null +++ b/dist/bower_components/angular-route/angular-route.min.js @@ -0,0 +1,14 @@ +/* + AngularJS v1.2.16 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(n,e,A){'use strict';function x(s,g,k){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,c,b,f,w){function y(){p&&(p.remove(),p=null);h&&(h.$destroy(),h=null);l&&(k.leave(l,function(){p=null}),p=l,l=null)}function v(){var b=s.current&&s.current.locals;if(e.isDefined(b&&b.$template)){var b=a.$new(),d=s.current;l=w(b,function(d){k.enter(d,null,l||c,function(){!e.isDefined(t)||t&&!a.$eval(t)||g()});y()});h=d.scope=b;h.$emit("$viewContentLoaded");h.$eval(u)}else y()} +var h,l,p,t=b.autoscroll,u=b.onload||"";a.$on("$routeChangeSuccess",v);v()}}}function z(e,g,k){return{restrict:"ECA",priority:-400,link:function(a,c){var b=k.current,f=b.locals;c.html(f.$template);var w=e(c.contents());b.controller&&(f.$scope=a,f=g(b.controller,f),b.controllerAs&&(a[b.controllerAs]=f),c.data("$ngControllerController",f),c.children().data("$ngControllerController",f));w(a)}}}n=e.module("ngRoute",["ng"]).provider("$route",function(){function s(a,c){return e.extend(new (e.extend(function(){}, +{prototype:a})),c)}function g(a,e){var b=e.caseInsensitiveMatch,f={originalPath:a,regexp:a},k=f.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,e,b,c){a="?"===c?c:null;c="*"===c?c:null;k.push({name:b,optional:!!a});e=e||"";return""+(a?"":e)+"(?:"+(a?e:"")+(c&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");f.regexp=RegExp("^"+a+"$",b?"i":"");return f}var k={};this.when=function(a,c){k[a]=e.extend({reloadOnSearch:!0},c,a&&g(a,c));if(a){var b= +"/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";k[b]=e.extend({redirectTo:a},g(b,c))}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(a,c,b,f,g,n,v,h){function l(){var d=p(),m=r.current;if(d&&m&&d.$$route===m.$$route&&e.equals(d.pathParams,m.pathParams)&&!d.reloadOnSearch&&!u)m.params=d.params,e.copy(m.params,b),a.$broadcast("$routeUpdate",m);else if(d||m)u=!1,a.$broadcast("$routeChangeStart", +d,m),(r.current=d)&&d.redirectTo&&(e.isString(d.redirectTo)?c.path(t(d.redirectTo,d.params)).search(d.params).replace():c.url(d.redirectTo(d.pathParams,c.path(),c.search())).replace()),f.when(d).then(function(){if(d){var a=e.extend({},d.resolve),c,b;e.forEach(a,function(d,c){a[c]=e.isString(d)?g.get(d):g.invoke(d)});e.isDefined(c=d.template)?e.isFunction(c)&&(c=c(d.params)):e.isDefined(b=d.templateUrl)&&(e.isFunction(b)&&(b=b(d.params)),b=h.getTrustedResourceUrl(b),e.isDefined(b)&&(d.loadedTemplateUrl= +b,c=n.get(b,{cache:v}).then(function(a){return a.data})));e.isDefined(c)&&(a.$template=c);return f.all(a)}}).then(function(c){d==r.current&&(d&&(d.locals=c,e.copy(d.params,b)),a.$broadcast("$routeChangeSuccess",d,m))},function(c){d==r.current&&a.$broadcast("$routeChangeError",d,m,c)})}function p(){var a,b;e.forEach(k,function(f,k){var q;if(q=!b){var g=c.path();q=f.keys;var l={};if(f.regexp)if(g=f.regexp.exec(g)){for(var h=1,p=g.length;h` to your `index.html`: + +```html + +``` + +And add `ngSanitize` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngSanitize']); +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/api/ngSanitize). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist/bower_components/angular-sanitize/angular-sanitize.js b/dist/bower_components/angular-sanitize/angular-sanitize.js new file mode 100644 index 000000000..b670812db --- /dev/null +++ b/dist/bower_components/angular-sanitize/angular-sanitize.js @@ -0,0 +1,624 @@ +/** + * @license AngularJS v1.2.16 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +var $sanitizeMinErr = angular.$$minErr('$sanitize'); + +/** + * @ngdoc module + * @name ngSanitize + * @description + * + * # ngSanitize + * + * The `ngSanitize` module provides functionality to sanitize HTML. + * + * + *
      + * + * See {@link ngSanitize.$sanitize `$sanitize`} for usage. + */ + +/* + * HTML Parser By Misko Hevery (misko@hevery.com) + * based on: HTML Parser By John Resig (ejohn.org) + * Original code by Erik Arvidsson, Mozilla Public License + * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js + * + * // Use like so: + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + */ + + +/** + * @ngdoc service + * @name $sanitize + * @function + * + * @description + * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are + * then serialized back to properly escaped html string. This means that no unsafe input can make + * it into the returned string, however, since our parser is more strict than a typical browser + * parser, it's possible that some obscure input, which would be recognized as valid HTML by a + * browser, won't make it through the sanitizer. + * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and + * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}. + * + * @param {string} html Html input. + * @returns {string} Sanitized html. + * + * @example + + + +
      + Snippet: + + + + + + + + + + + + + + + + + + + + + + + + + +
      DirectiveHowSourceRendered
      ng-bind-htmlAutomatically uses $sanitize
      <div ng-bind-html="snippet">
      </div>
      ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value +
      <div ng-bind-html="deliberatelyTrustDangerousSnippet()">
      +</div>
      +
      ng-bindAutomatically escapes
      <div ng-bind="snippet">
      </div>
      +
      +
      + + it('should sanitize the html snippet by default', function() { + expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). + toBe('

      an html\nclick here\nsnippet

      '); + }); + + it('should inline raw snippet if bound to a trusted value', function() { + expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()). + toBe("

      an html\n" + + "click here\n" + + "snippet

      "); + }); + + it('should escape snippet without any filter', function() { + expect(element(by.css('#bind-default div')).getInnerHtml()). + toBe("<p style=\"color:blue\">an html\n" + + "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + + "snippet</p>"); + }); + + it('should update', function() { + element(by.model('snippet')).clear(); + element(by.model('snippet')).sendKeys('new text'); + expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). + toBe('new text'); + expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe( + 'new text'); + expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( + "new <b onclick=\"alert(1)\">text</b>"); + }); +
      +
      + */ +function $SanitizeProvider() { + this.$get = ['$$sanitizeUri', function($$sanitizeUri) { + return function(html) { + var buf = []; + htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { + return !/^unsafe/.test($$sanitizeUri(uri, isImage)); + })); + return buf.join(''); + }; + }]; +} + +function sanitizeText(chars) { + var buf = []; + var writer = htmlSanitizeWriter(buf, angular.noop); + writer.chars(chars); + return buf.join(''); +} + + +// Regular Expressions for parsing tags and attributes +var START_TAG_REGEXP = + /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, + END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, + ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, + BEGIN_TAG_REGEXP = /^/g, + DOCTYPE_REGEXP = /]*?)>/i, + CDATA_REGEXP = //g, + // Match everything outside of normal chars and " (quote character) + NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; + + +// Good source of info about elements and attributes +// http://dev.w3.org/html5/spec/Overview.html#semantics +// http://simon.html5.org/html-elements + +// Safe Void Elements - HTML5 +// http://dev.w3.org/html5/spec/Overview.html#void-elements +var voidElements = makeMap("area,br,col,hr,img,wbr"); + +// Elements that you can, intentionally, leave open (and which close themselves) +// http://dev.w3.org/html5/spec/Overview.html#optional-tags +var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), + optionalEndTagInlineElements = makeMap("rp,rt"), + optionalEndTagElements = angular.extend({}, + optionalEndTagInlineElements, + optionalEndTagBlockElements); + +// Safe Block Elements - HTML5 +var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + + "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + + "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); + +// Inline Elements - HTML5 +var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + + "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + + "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); + + +// Special Elements (can contain anything) +var specialElements = makeMap("script,style"); + +var validElements = angular.extend({}, + voidElements, + blockElements, + inlineElements, + optionalEndTagElements); + +//Attributes that have href and hence need to be sanitized +var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); +var validAttrs = angular.extend({}, uriAttrs, makeMap( + 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ + 'scope,scrolling,shape,size,span,start,summary,target,title,type,'+ + 'valign,value,vspace,width')); + +function makeMap(str) { + var obj = {}, items = str.split(','), i; + for (i = 0; i < items.length; i++) obj[items[i]] = true; + return obj; +} + + +/** + * @example + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + * @param {string} html string + * @param {object} handler + */ +function htmlParser( html, handler ) { + var index, chars, match, stack = [], last = html; + stack.last = function() { return stack[ stack.length - 1 ]; }; + + while ( html ) { + chars = true; + + // Make sure we're not in a script or style element + if ( !stack.last() || !specialElements[ stack.last() ] ) { + + // Comment + if ( html.indexOf("", index) === index) { + if (handler.comment) handler.comment( html.substring( 4, index ) ); + html = html.substring( index + 3 ); + chars = false; + } + // DOCTYPE + } else if ( DOCTYPE_REGEXP.test(html) ) { + match = html.match( DOCTYPE_REGEXP ); + + if ( match ) { + html = html.replace( match[0], ''); + chars = false; + } + // end tag + } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { + match = html.match( END_TAG_REGEXP ); + + if ( match ) { + html = html.substring( match[0].length ); + match[0].replace( END_TAG_REGEXP, parseEndTag ); + chars = false; + } + + // start tag + } else if ( BEGIN_TAG_REGEXP.test(html) ) { + match = html.match( START_TAG_REGEXP ); + + if ( match ) { + html = html.substring( match[0].length ); + match[0].replace( START_TAG_REGEXP, parseStartTag ); + chars = false; + } + } + + if ( chars ) { + index = html.indexOf("<"); + + var text = index < 0 ? html : html.substring( 0, index ); + html = index < 0 ? "" : html.substring( index ); + + if (handler.chars) handler.chars( decodeEntities(text) ); + } + + } else { + html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), + function(all, text){ + text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); + + if (handler.chars) handler.chars( decodeEntities(text) ); + + return ""; + }); + + parseEndTag( "", stack.last() ); + } + + if ( html == last ) { + throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + + "of html: {0}", html); + } + last = html; + } + + // Clean up any remaining tags + parseEndTag(); + + function parseStartTag( tag, tagName, rest, unary ) { + tagName = angular.lowercase(tagName); + if ( blockElements[ tagName ] ) { + while ( stack.last() && inlineElements[ stack.last() ] ) { + parseEndTag( "", stack.last() ); + } + } + + if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { + parseEndTag( "", tagName ); + } + + unary = voidElements[ tagName ] || !!unary; + + if ( !unary ) + stack.push( tagName ); + + var attrs = {}; + + rest.replace(ATTR_REGEXP, + function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { + var value = doubleQuotedValue + || singleQuotedValue + || unquotedValue + || ''; + + attrs[name] = decodeEntities(value); + }); + if (handler.start) handler.start( tagName, attrs, unary ); + } + + function parseEndTag( tag, tagName ) { + var pos = 0, i; + tagName = angular.lowercase(tagName); + if ( tagName ) + // Find the closest opened tag of the same type + for ( pos = stack.length - 1; pos >= 0; pos-- ) + if ( stack[ pos ] == tagName ) + break; + + if ( pos >= 0 ) { + // Close all the open elements, up the stack + for ( i = stack.length - 1; i >= pos; i-- ) + if (handler.end) handler.end( stack[ i ] ); + + // Remove the open elements from the stack + stack.length = pos; + } + } +} + +var hiddenPre=document.createElement("pre"); +var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; +/** + * decodes all entities into regular string + * @param value + * @returns {string} A string with decoded entities. + */ +function decodeEntities(value) { + if (!value) { return ''; } + + // Note: IE8 does not preserve spaces at the start/end of innerHTML + // so we must capture them and reattach them afterward + var parts = spaceRe.exec(value); + var spaceBefore = parts[1]; + var spaceAfter = parts[3]; + var content = parts[2]; + if (content) { + hiddenPre.innerHTML=content.replace(//g, '>'); +} + +/** + * create an HTML/XML writer which writes to buffer + * @param {Array} buf use buf.jain('') to get out sanitized html string + * @returns {object} in the form of { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * } + */ +function htmlSanitizeWriter(buf, uriValidator){ + var ignore = false; + var out = angular.bind(buf, buf.push); + return { + start: function(tag, attrs, unary){ + tag = angular.lowercase(tag); + if (!ignore && specialElements[tag]) { + ignore = tag; + } + if (!ignore && validElements[tag] === true) { + out('<'); + out(tag); + angular.forEach(attrs, function(value, key){ + var lkey=angular.lowercase(key); + var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); + if (validAttrs[lkey] === true && + (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { + out(' '); + out(key); + out('="'); + out(encodeEntities(value)); + out('"'); + } + }); + out(unary ? '/>' : '>'); + } + }, + end: function(tag){ + tag = angular.lowercase(tag); + if (!ignore && validElements[tag] === true) { + out(''); + } + if (tag == ignore) { + ignore = false; + } + }, + chars: function(chars){ + if (!ignore) { + out(encodeEntities(chars)); + } + } + }; +} + + +// define ngSanitize module and register $sanitize service +angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); + +/* global sanitizeText: false */ + +/** + * @ngdoc filter + * @name linky + * @function + * + * @description + * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and + * plain email address links. + * + * Requires the {@link ngSanitize `ngSanitize`} module to be installed. + * + * @param {string} text Input text. + * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. + * @returns {string} Html-linkified text. + * + * @usage + + * + * @example + + + +
      + Snippet: + + + + + + + + + + + + + + + + + + + + + +
      FilterSourceRendered
      linky filter +
      <div ng-bind-html="snippet | linky">
      </div>
      +
      +
      +
      linky target +
      <div ng-bind-html="snippetWithTarget | linky:'_blank'">
      </div>
      +
      +
      +
      no filter
      <div ng-bind="snippet">
      </div>
      + + + it('should linkify the snippet with urls', function() { + expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). + toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' + + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); + expect(element.all(by.css('#linky-filter a')).count()).toEqual(4); + }); + + it('should not linkify snippet without the linky filter', function() { + expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()). + toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' + + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); + expect(element.all(by.css('#escaped-html a')).count()).toEqual(0); + }); + + it('should update', function() { + element(by.model('snippet')).clear(); + element(by.model('snippet')).sendKeys('new http://link.'); + expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). + toBe('new http://link.'); + expect(element.all(by.css('#linky-filter a')).count()).toEqual(1); + expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()) + .toBe('new http://link.'); + }); + + it('should work with the target property', function() { + expect(element(by.id('linky-target')). + element(by.binding("snippetWithTarget | linky:'_blank'")).getText()). + toBe('http://angularjs.org/'); + expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank'); + }); + + + */ +angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { + var LINKY_URL_REGEXP = + /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/, + MAILTO_REGEXP = /^mailto:/; + + return function(text, target) { + if (!text) return text; + var match; + var raw = text; + var html = []; + var url; + var i; + while ((match = raw.match(LINKY_URL_REGEXP))) { + // We can not end in these as they are sometimes found at the end of the sentence + url = match[0]; + // if we did not match ftp/http/mailto then assume mailto + if (match[2] == match[3]) url = 'mailto:' + url; + i = match.index; + addText(raw.substr(0, i)); + addLink(url, match[0].replace(MAILTO_REGEXP, '')); + raw = raw.substring(i + match[0].length); + } + addText(raw); + return $sanitize(html.join('')); + + function addText(text) { + if (!text) { + return; + } + html.push(sanitizeText(text)); + } + + function addLink(url, text) { + html.push(''); + addText(text); + html.push(''); + } + }; +}]); + + +})(window, window.angular); diff --git a/dist/bower_components/angular-sanitize/angular-sanitize.min.js b/dist/bower_components/angular-sanitize/angular-sanitize.min.js new file mode 100644 index 000000000..08964713b --- /dev/null +++ b/dist/bower_components/angular-sanitize/angular-sanitize.min.js @@ -0,0 +1,14 @@ +/* + AngularJS v1.2.16 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(p,h,q){'use strict';function E(a){var e=[];s(e,h.noop).chars(a);return e.join("")}function k(a){var e={};a=a.split(",");var d;for(d=0;d=c;d--)e.end&&e.end(f[d]);f.length=c}}var b,g,f=[],l=a;for(f.last=function(){return f[f.length-1]};a;){g=!0;if(f.last()&&x[f.last()])a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(b,a){a=a.replace(H,"$1").replace(I,"$1");e.chars&&e.chars(r(a));return""}),c("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(e.comment&&e.comment(a.substring(4,b)),a=a.substring(b+3),g=!1);else if(y.test(a)){if(b=a.match(y))a= +a.replace(b[0],""),g=!1}else if(J.test(a)){if(b=a.match(z))a=a.substring(b[0].length),b[0].replace(z,c),g=!1}else K.test(a)&&(b=a.match(A))&&(a=a.substring(b[0].length),b[0].replace(A,d),g=!1);g&&(b=a.indexOf("<"),g=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),e.chars&&e.chars(r(g)))}if(a==l)throw L("badparse",a);l=a}c()}function r(a){if(!a)return"";var e=M.exec(a);a=e[1];var d=e[3];if(e=e[2])n.innerHTML=e.replace(//g,">")}function s(a,e){var d=!1,c=h.bind(a,a.push);return{start:function(a,g,f){a=h.lowercase(a);!d&&x[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(g,function(d,f){var g=h.lowercase(f),k="img"===a&&"src"===g||"background"===g;!0!==O[g]||!0===D[g]&&!e(d,k)||(c(" "),c(f),c('="'),c(B(d)),c('"'))}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c(""));a==d&&(d=!1)},chars:function(a){d|| +c(B(a))}}}var L=h.$$minErr("$sanitize"),A=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,z=/^<\s*\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^]*?)>/i,I=/]/,d=/^mailto:/;return function(c,b){function g(a){a&&m.push(E(a))}function f(a,c){m.push("');g(c);m.push("")}if(!c)return c;for(var l,k=c,m=[],n,p;l=k.match(e);)n=l[0],l[2]==l[3]&&(n="mailto:"+n),p=l.index,g(k.substr(0,p)),f(n,l[0].replace(d,"")),k=k.substring(p+l[0].length);g(k);return a(m.join(""))}}])})(window,window.angular); +//# sourceMappingURL=angular-sanitize.min.js.map diff --git a/dist/bower_components/angular-sanitize/angular-sanitize.min.js.map b/dist/bower_components/angular-sanitize/angular-sanitize.min.js.map new file mode 100644 index 000000000..dbf6b259b --- /dev/null +++ b/dist/bower_components/angular-sanitize/angular-sanitize.min.js.map @@ -0,0 +1,8 @@ +{ +"version":3, +"file":"angular-sanitize.min.js", +"lineCount":13, +"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAiJtCC,QAASA,EAAY,CAACC,CAAD,CAAQ,CAC3B,IAAIC,EAAM,EACGC,EAAAC,CAAmBF,CAAnBE,CAAwBN,CAAAO,KAAxBD,CACbH,MAAA,CAAaA,CAAb,CACA,OAAOC,EAAAI,KAAA,CAAS,EAAT,CAJoB,CAmE7BC,QAASA,EAAO,CAACC,CAAD,CAAM,CAAA,IAChBC,EAAM,EAAIC,EAAAA,CAAQF,CAAAG,MAAA,CAAU,GAAV,CAAtB,KAAsCC,CACtC,KAAKA,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgBF,CAAAG,OAAhB,CAA8BD,CAAA,EAA9B,CAAmCH,CAAA,CAAIC,CAAA,CAAME,CAAN,CAAJ,CAAA,CAAgB,CAAA,CACnD,OAAOH,EAHa,CAmBtBK,QAASA,EAAU,CAAEC,CAAF,CAAQC,CAAR,CAAkB,CAiFnCC,QAASA,EAAa,CAAEC,CAAF,CAAOC,CAAP,CAAgBC,CAAhB,CAAsBC,CAAtB,CAA8B,CAClDF,CAAA,CAAUrB,CAAAwB,UAAA,CAAkBH,CAAlB,CACV,IAAKI,CAAA,CAAeJ,CAAf,CAAL,CACE,IAAA,CAAQK,CAAAC,KAAA,EAAR,EAAwBC,CAAA,CAAgBF,CAAAC,KAAA,EAAhB,CAAxB,CAAA,CACEE,CAAA,CAAa,EAAb,CAAiBH,CAAAC,KAAA,EAAjB,CAICG,EAAA,CAAwBT,CAAxB,CAAL,EAA0CK,CAAAC,KAAA,EAA1C,EAA0DN,CAA1D,EACEQ,CAAA,CAAa,EAAb,CAAiBR,CAAjB,CAKF,EAFAE,CAEA,CAFQQ,CAAA,CAAcV,CAAd,CAER,EAFmC,CAAC,CAACE,CAErC,GACEG,CAAAM,KAAA,CAAYX,CAAZ,CAEF,KAAIY,EAAQ,EAEZX,EAAAY,QAAA,CAAaC,CAAb,CACE,QAAQ,CAACC,CAAD,CAAQC,CAAR,CAAcC,CAAd,CAAiCC,CAAjC,CAAoDC,CAApD,CAAmE,CAMzEP,CAAA,CAAMI,CAAN,CAAA,CAAcI,CAAA,CALFH,CAKE,EAJTC,CAIS,EAHTC,CAGS,EAFT,EAES,CAN2D,CAD7E,CASItB,EAAAwB,MAAJ,EAAmBxB,CAAAwB,MAAA,CAAerB,CAAf,CAAwBY,CAAxB,CAA+BV,CAA/B,CA5B+B,CA+BpDM,QAASA,EAAW,CAAET,CAAF,CAAOC,CAAP,CAAiB,CAAA,IAC/BsB,EAAM,CADyB,CACtB7B,CAEb,IADAO,CACA,CADUrB,CAAAwB,UAAA,CAAkBH,CAAlB,CACV,CAEE,IAAMsB,CAAN,CAAYjB,CAAAX,OAAZ,CAA2B,CAA3B,CAAqC,CAArC,EAA8B4B,CAA9B,EACOjB,CAAA,CAAOiB,CAAP,CADP,EACuBtB,CADvB,CAAwCsB,CAAA,EAAxC;AAIF,GAAY,CAAZ,EAAKA,CAAL,CAAgB,CAEd,IAAM7B,CAAN,CAAUY,CAAAX,OAAV,CAAyB,CAAzB,CAA4BD,CAA5B,EAAiC6B,CAAjC,CAAsC7B,CAAA,EAAtC,CACMI,CAAA0B,IAAJ,EAAiB1B,CAAA0B,IAAA,CAAalB,CAAA,CAAOZ,CAAP,CAAb,CAGnBY,EAAAX,OAAA,CAAe4B,CAND,CATmB,CAhHF,IAC/BE,CAD+B,CACxB1C,CADwB,CACVuB,EAAQ,EADE,CACEC,EAAOV,CAG5C,KAFAS,CAAAC,KAEA,CAFamB,QAAQ,EAAG,CAAE,MAAOpB,EAAA,CAAOA,CAAAX,OAAP,CAAsB,CAAtB,CAAT,CAExB,CAAQE,CAAR,CAAA,CAAe,CACbd,CAAA,CAAQ,CAAA,CAGR,IAAMuB,CAAAC,KAAA,EAAN,EAAuBoB,CAAA,CAAiBrB,CAAAC,KAAA,EAAjB,CAAvB,CAmDEV,CASA,CATOA,CAAAiB,QAAA,CAAiBc,MAAJ,CAAW,kBAAX,CAAgCtB,CAAAC,KAAA,EAAhC,CAA+C,QAA/C,CAAyD,GAAzD,CAAb,CACL,QAAQ,CAACsB,CAAD,CAAMC,CAAN,CAAW,CACjBA,CAAA,CAAOA,CAAAhB,QAAA,CAAaiB,CAAb,CAA6B,IAA7B,CAAAjB,QAAA,CAA2CkB,CAA3C,CAAyD,IAAzD,CAEHlC,EAAAf,MAAJ,EAAmBe,CAAAf,MAAA,CAAesC,CAAA,CAAeS,CAAf,CAAf,CAEnB,OAAO,EALU,CADd,CASP,CAAArB,CAAA,CAAa,EAAb,CAAiBH,CAAAC,KAAA,EAAjB,CA5DF,KAAyD,CAGvD,GAA8B,CAA9B,GAAKV,CAAAoC,QAAA,CAAa,SAAb,CAAL,CAEER,CAEA,CAFQ5B,CAAAoC,QAAA,CAAa,IAAb,CAAmB,CAAnB,CAER,CAAc,CAAd,EAAKR,CAAL,EAAmB5B,CAAAqC,YAAA,CAAiB,QAAjB,CAAwBT,CAAxB,CAAnB,GAAsDA,CAAtD,GACM3B,CAAAqC,QAEJ,EAFqBrC,CAAAqC,QAAA,CAAiBtC,CAAAuC,UAAA,CAAgB,CAAhB,CAAmBX,CAAnB,CAAjB,CAErB,CADA5B,CACA,CADOA,CAAAuC,UAAA,CAAgBX,CAAhB,CAAwB,CAAxB,CACP,CAAA1C,CAAA,CAAQ,CAAA,CAHV,CAJF,KAUO,IAAKsD,CAAAC,KAAA,CAAoBzC,CAApB,CAAL,CAGL,IAFAmB,CAEA,CAFQnB,CAAAmB,MAAA,CAAYqB,CAAZ,CAER,CACExC,CACA;AADOA,CAAAiB,QAAA,CAAcE,CAAA,CAAM,CAAN,CAAd,CAAwB,EAAxB,CACP,CAAAjC,CAAA,CAAQ,CAAA,CAFV,CAHK,IAQA,IAAKwD,CAAAD,KAAA,CAA4BzC,CAA5B,CAAL,CAGL,IAFAmB,CAEA,CAFQnB,CAAAmB,MAAA,CAAYwB,CAAZ,CAER,CACE3C,CAEA,CAFOA,CAAAuC,UAAA,CAAgBpB,CAAA,CAAM,CAAN,CAAArB,OAAhB,CAEP,CADAqB,CAAA,CAAM,CAAN,CAAAF,QAAA,CAAkB0B,CAAlB,CAAkC/B,CAAlC,CACA,CAAA1B,CAAA,CAAQ,CAAA,CAHV,CAHK,IAUK0D,EAAAH,KAAA,CAAsBzC,CAAtB,CAAL,GACLmB,CADK,CACGnB,CAAAmB,MAAA,CAAY0B,CAAZ,CADH,IAIH7C,CAEA,CAFOA,CAAAuC,UAAA,CAAgBpB,CAAA,CAAM,CAAN,CAAArB,OAAhB,CAEP,CADAqB,CAAA,CAAM,CAAN,CAAAF,QAAA,CAAkB4B,CAAlB,CAAoC3C,CAApC,CACA,CAAAhB,CAAA,CAAQ,CAAA,CANL,CAUFA,EAAL,GACE0C,CAKA,CALQ5B,CAAAoC,QAAA,CAAa,GAAb,CAKR,CAHIH,CAGJ,CAHmB,CAAR,CAAAL,CAAA,CAAY5B,CAAZ,CAAmBA,CAAAuC,UAAA,CAAgB,CAAhB,CAAmBX,CAAnB,CAG9B,CAFA5B,CAEA,CAFe,CAAR,CAAA4B,CAAA,CAAY,EAAZ,CAAiB5B,CAAAuC,UAAA,CAAgBX,CAAhB,CAExB,CAAI3B,CAAAf,MAAJ,EAAmBe,CAAAf,MAAA,CAAesC,CAAA,CAAeS,CAAf,CAAf,CANrB,CAzCuD,CA+DzD,GAAKjC,CAAL,EAAaU,CAAb,CACE,KAAMoC,EAAA,CAAgB,UAAhB,CAC4C9C,CAD5C,CAAN,CAGFU,CAAA,CAAOV,CAvEM,CA2EfY,CAAA,EA/EmC,CA2IrCY,QAASA,EAAc,CAACuB,CAAD,CAAQ,CAC7B,GAAI,CAACA,CAAL,CAAc,MAAO,EAIrB,KAAIC,EAAQC,CAAAC,KAAA,CAAaH,CAAb,CACRI,EAAAA,CAAcH,CAAA,CAAM,CAAN,CAClB,KAAII,EAAaJ,CAAA,CAAM,CAAN,CAEjB,IADIK,CACJ,CADcL,CAAA,CAAM,CAAN,CACd,CACEM,CAAAC,UAKA,CALoBF,CAAApC,QAAA,CAAgB,IAAhB,CAAqB,MAArB,CAKpB,CAAAoC,CAAA,CAAU,aAAA,EAAiBC,EAAjB,CACRA,CAAAE,YADQ,CACgBF,CAAAG,UAE5B,OAAON,EAAP,CAAqBE,CAArB,CAA+BD,CAlBF,CA4B/BM,QAASA,EAAc,CAACX,CAAD,CAAQ,CAC7B,MAAOA,EAAA9B,QAAA,CACG,IADH;AACS,OADT,CAAAA,QAAA,CAEG0C,CAFH,CAE4B,QAAQ,CAACZ,CAAD,CAAO,CAC9C,MAAO,IAAP,CAAcA,CAAAa,WAAA,CAAiB,CAAjB,CAAd,CAAoC,GADU,CAF3C,CAAA3C,QAAA,CAKG,IALH,CAKS,MALT,CAAAA,QAAA,CAMG,IANH,CAMS,MANT,CADsB,CAoB/B7B,QAASA,EAAkB,CAACD,CAAD,CAAM0E,CAAN,CAAmB,CAC5C,IAAIC,EAAS,CAAA,CAAb,CACIC,EAAMhF,CAAAiF,KAAA,CAAa7E,CAAb,CAAkBA,CAAA4B,KAAlB,CACV,OAAO,OACEU,QAAQ,CAACtB,CAAD,CAAMa,CAAN,CAAaV,CAAb,CAAmB,CAChCH,CAAA,CAAMpB,CAAAwB,UAAA,CAAkBJ,CAAlB,CACD2D,EAAAA,CAAL,EAAehC,CAAA,CAAgB3B,CAAhB,CAAf,GACE2D,CADF,CACW3D,CADX,CAGK2D,EAAL,EAAsC,CAAA,CAAtC,GAAeG,CAAA,CAAc9D,CAAd,CAAf,GACE4D,CAAA,CAAI,GAAJ,CAcA,CAbAA,CAAA,CAAI5D,CAAJ,CAaA,CAZApB,CAAAmF,QAAA,CAAgBlD,CAAhB,CAAuB,QAAQ,CAAC+B,CAAD,CAAQoB,CAAR,CAAY,CACzC,IAAIC,EAAKrF,CAAAwB,UAAA,CAAkB4D,CAAlB,CAAT,CACIE,EAAmB,KAAnBA,GAAWlE,CAAXkE,EAAqC,KAArCA,GAA4BD,CAA5BC,EAAyD,YAAzDA,GAAgDD,CAC3B,EAAA,CAAzB,GAAIE,CAAA,CAAWF,CAAX,CAAJ,EACsB,CAAA,CADtB,GACGG,CAAA,CAASH,CAAT,CADH,EAC8B,CAAAP,CAAA,CAAad,CAAb,CAAoBsB,CAApB,CAD9B,GAEEN,CAAA,CAAI,GAAJ,CAIA,CAHAA,CAAA,CAAII,CAAJ,CAGA,CAFAJ,CAAA,CAAI,IAAJ,CAEA,CADAA,CAAA,CAAIL,CAAA,CAAeX,CAAf,CAAJ,CACA,CAAAgB,CAAA,CAAI,GAAJ,CANF,CAHyC,CAA3C,CAYA,CAAAA,CAAA,CAAIzD,CAAA,CAAQ,IAAR,CAAe,GAAnB,CAfF,CALgC,CAD7B,KAwBAqB,QAAQ,CAACxB,CAAD,CAAK,CACdA,CAAA,CAAMpB,CAAAwB,UAAA,CAAkBJ,CAAlB,CACD2D,EAAL,EAAsC,CAAA,CAAtC,GAAeG,CAAA,CAAc9D,CAAd,CAAf,GACE4D,CAAA,CAAI,IAAJ,CAEA,CADAA,CAAA,CAAI5D,CAAJ,CACA,CAAA4D,CAAA,CAAI,GAAJ,CAHF,CAKI5D,EAAJ,EAAW2D,CAAX,GACEA,CADF,CACW,CAAA,CADX,CAPc,CAxBb,OAmCE5E,QAAQ,CAACA,CAAD,CAAO,CACb4E,CAAL;AACEC,CAAA,CAAIL,CAAA,CAAexE,CAAf,CAAJ,CAFgB,CAnCjB,CAHqC,CAha9C,IAAI4D,EAAkB/D,CAAAyF,SAAA,CAAiB,WAAjB,CAAtB,CAwJI3B,EACG,4FAzJP,CA0JEF,EAAiB,2BA1JnB,CA2JEzB,EAAc,yEA3JhB,CA4JE0B,EAAmB,IA5JrB,CA6JEF,EAAyB,SA7J3B,CA8JER,EAAiB,qBA9JnB,CA+JEM,EAAiB,qBA/JnB,CAgKEL,EAAe,yBAhKjB,CAkKEwB,EAA0B,gBAlK5B,CA2KI7C,EAAetB,CAAA,CAAQ,wBAAR,CAIfiF,EAAAA,CAA8BjF,CAAA,CAAQ,gDAAR,CAC9BkF,EAAAA,CAA+BlF,CAAA,CAAQ,OAAR,CADnC,KAEIqB,EAAyB9B,CAAA4F,OAAA,CAAe,EAAf,CACeD,CADf,CAEeD,CAFf,CAF7B,CAOIjE,EAAgBzB,CAAA4F,OAAA,CAAe,EAAf,CAAmBF,CAAnB,CAAgDjF,CAAA,CAAQ,4KAAR,CAAhD,CAPpB;AAYImB,EAAiB5B,CAAA4F,OAAA,CAAe,EAAf,CAAmBD,CAAnB,CAAiDlF,CAAA,CAAQ,2JAAR,CAAjD,CAZrB,CAkBIsC,EAAkBtC,CAAA,CAAQ,cAAR,CAlBtB,CAoBIyE,EAAgBlF,CAAA4F,OAAA,CAAe,EAAf,CACe7D,CADf,CAEeN,CAFf,CAGeG,CAHf,CAIeE,CAJf,CApBpB,CA2BI0D,EAAW/E,CAAA,CAAQ,0CAAR,CA3Bf,CA4BI8E,EAAavF,CAAA4F,OAAA,CAAe,EAAf,CAAmBJ,CAAnB,CAA6B/E,CAAA,CAC1C,ySAD0C,CAA7B,CA5BjB;AA0LI8D,EAAUsB,QAAAC,cAAA,CAAuB,KAAvB,CA1Ld,CA2LI5B,EAAU,wBAsGdlE,EAAA+F,OAAA,CAAe,YAAf,CAA6B,EAA7B,CAAAC,SAAA,CAA0C,WAA1C,CA7UAC,QAA0B,EAAG,CAC3B,IAAAC,KAAA,CAAY,CAAC,eAAD,CAAkB,QAAQ,CAACC,CAAD,CAAgB,CACpD,MAAO,SAAQ,CAAClF,CAAD,CAAO,CACpB,IAAIb,EAAM,EACVY,EAAA,CAAWC,CAAX,CAAiBZ,CAAA,CAAmBD,CAAnB,CAAwB,QAAQ,CAACgG,CAAD,CAAMd,CAAN,CAAe,CAC9D,MAAO,CAAC,SAAA5B,KAAA,CAAeyC,CAAA,CAAcC,CAAd,CAAmBd,CAAnB,CAAf,CADsD,CAA/C,CAAjB,CAGA,OAAOlF,EAAAI,KAAA,CAAS,EAAT,CALa,CAD8B,CAA1C,CADe,CA6U7B,CAuGAR,EAAA+F,OAAA,CAAe,YAAf,CAAAM,OAAA,CAAoC,OAApC,CAA6C,CAAC,WAAD,CAAc,QAAQ,CAACC,CAAD,CAAY,CAAA,IACzEC,EACE,mEAFuE,CAGzEC,EAAgB,UAEpB,OAAO,SAAQ,CAACtD,CAAD,CAAOuD,CAAP,CAAe,CAoB5BC,QAASA,EAAO,CAACxD,CAAD,CAAO,CAChBA,CAAL,EAGAjC,CAAAe,KAAA,CAAU9B,CAAA,CAAagD,CAAb,CAAV,CAJqB,CAOvByD,QAASA,EAAO,CAACC,CAAD,CAAM1D,CAAN,CAAY,CAC1BjC,CAAAe,KAAA,CAAU,KAAV,CACIhC,EAAA6G,UAAA,CAAkBJ,CAAlB,CAAJ;CACExF,CAAAe,KAAA,CAAU,UAAV,CAEA,CADAf,CAAAe,KAAA,CAAUyE,CAAV,CACA,CAAAxF,CAAAe,KAAA,CAAU,IAAV,CAHF,CAKAf,EAAAe,KAAA,CAAU,QAAV,CACAf,EAAAe,KAAA,CAAU4E,CAAV,CACA3F,EAAAe,KAAA,CAAU,IAAV,CACA0E,EAAA,CAAQxD,CAAR,CACAjC,EAAAe,KAAA,CAAU,MAAV,CAX0B,CA1B5B,GAAI,CAACkB,CAAL,CAAW,MAAOA,EAMlB,KALA,IAAId,CAAJ,CACI0E,EAAM5D,CADV,CAEIjC,EAAO,EAFX,CAGI2F,CAHJ,CAII9F,CACJ,CAAQsB,CAAR,CAAgB0E,CAAA1E,MAAA,CAAUmE,CAAV,CAAhB,CAAA,CAEEK,CAMA,CANMxE,CAAA,CAAM,CAAN,CAMN,CAJIA,CAAA,CAAM,CAAN,CAIJ,EAJgBA,CAAA,CAAM,CAAN,CAIhB,GAJ0BwE,CAI1B,CAJgC,SAIhC,CAJ4CA,CAI5C,EAHA9F,CAGA,CAHIsB,CAAAS,MAGJ,CAFA6D,CAAA,CAAQI,CAAAC,OAAA,CAAW,CAAX,CAAcjG,CAAd,CAAR,CAEA,CADA6F,CAAA,CAAQC,CAAR,CAAaxE,CAAA,CAAM,CAAN,CAAAF,QAAA,CAAiBsE,CAAjB,CAAgC,EAAhC,CAAb,CACA,CAAAM,CAAA,CAAMA,CAAAtD,UAAA,CAAc1C,CAAd,CAAkBsB,CAAA,CAAM,CAAN,CAAArB,OAAlB,CAER2F,EAAA,CAAQI,CAAR,CACA,OAAOR,EAAA,CAAUrF,CAAAT,KAAA,CAAU,EAAV,CAAV,CAlBqB,CAL+C,CAAlC,CAA7C,CAzjBsC,CAArC,CAAA,CA0mBET,MA1mBF,CA0mBUA,MAAAC,QA1mBV;", +"sources":["angular-sanitize.js"], +"names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","makeMap","str","obj","items","split","i","length","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","lowercase","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","stack.last","specialElements","RegExp","all","text","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","parts","spaceRe","exec","spaceBefore","spaceAfter","content","hiddenPre","innerHTML","textContent","innerText","encodeEntities","NON_ALPHANUMERIC_REGEXP","charCodeAt","uriValidator","ignore","out","bind","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","document","createElement","module","provider","$SanitizeProvider","$get","$$sanitizeUri","uri","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","target","addText","addLink","url","isDefined","raw","substr"] +} diff --git a/dist/bower_components/angular-sanitize/bower.json b/dist/bower_components/angular-sanitize/bower.json new file mode 100644 index 000000000..1160f22ff --- /dev/null +++ b/dist/bower_components/angular-sanitize/bower.json @@ -0,0 +1,8 @@ +{ + "name": "angular-sanitize", + "version": "1.2.16", + "main": "./angular-sanitize.js", + "dependencies": { + "angular": "1.2.16" + } +} diff --git a/dist/bower_components/angular-scenario/.bower.json b/dist/bower_components/angular-scenario/.bower.json new file mode 100644 index 000000000..e86e02f7f --- /dev/null +++ b/dist/bower_components/angular-scenario/.bower.json @@ -0,0 +1,18 @@ +{ + "name": "angular-scenario", + "version": "1.2.8", + "main": "./angular-scenario.js", + "dependencies": { + "angular": "1.2.8" + }, + "homepage": "https://github.com/angular/bower-angular-scenario", + "_release": "1.2.8", + "_resolution": { + "type": "version", + "tag": "v1.2.8", + "commit": "ad9ea87eca812bb19e8631ffa9573aef6b14c65f" + }, + "_source": "git://github.com/angular/bower-angular-scenario.git", + "_target": "1.2.8", + "_originalSource": "angular-scenario" +} \ No newline at end of file diff --git a/dist/bower_components/angular-scenario/README.md b/dist/bower_components/angular-scenario/README.md new file mode 100644 index 000000000..7f80a8c55 --- /dev/null +++ b/dist/bower_components/angular-scenario/README.md @@ -0,0 +1,42 @@ +# bower-angular-scenario + +This repo is for distribution on `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngScenario). +Please file issues and pull requests against that repo. + +## Install + +Install with `bower`: + +```shell +bower install angular-scenario +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/dist/bower_components/angular-scenario/angular-scenario.js b/dist/bower_components/angular-scenario/angular-scenario.js new file mode 100644 index 000000000..a6b4ac25b --- /dev/null +++ b/dist/bower_components/angular-scenario/angular-scenario.js @@ -0,0 +1,32560 @@ +/*! + * jQuery JavaScript Library v1.10.2 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03T13:48Z + */ +(function( window, undefined ) {'use strict'; + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +// + +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.2", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.10.2 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent.attachEvent && parent !== parent.top ) { + parent.attachEvent( "onbeforeunload", function() { + setDocument(); + }); + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "
      "; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; + } + }); +} + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
      a"; + + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; + a = div.getElementsByTagName("a")[ 0 ]; + if ( !a || !a.style || !all.length ) { + return support; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
      t
      "; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior. + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
      "; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})({}); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + data = null, + i = 0, + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + return tabindex ? + parseInt( tabindex, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = { + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }; + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = ret.push( cur ); + break; + } + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
      ", "
      " ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
      " ], + tr: [ 2, "", "
      " ], + col: [ 2, "", "
      " ], + td: [ 3, "", "
      " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
      ", "
      " ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
      " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each(function() { + if ( isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery(" + + + + +
      +
      +

      + Mattia Larentis · Peter Stein · Emanuele Marchi +

      + + +
      +
      +
      +
      +
      + + + + + +
      +
      +

      Change the size programmatically:

      + +
      +
      + + + + +
      +
      <input type="checkbox" checked class="switch-large">
      +<input type="checkbox" checked>
      +<input type="checkbox" checked class="switch-small">
      +<input type="checkbox" checked class="switch-mini">
      +<input id="dimension-switch" type="checkbox" checked>
      +
      // Resets to the regular style
      +$('#dimension-switch').bootstrapSwitch('setSizeClass', '');
      +
      +// Sets a mini switch
      +$('#dimension-switch').bootstrapSwitch('setSizeClass', 'switch-mini');
      +
      +// Sets a small switch
      +$('#dimension-switch').bootstrapSwitch('setSizeClass', 'switch-small');
      +
      +// Sets a large switch
      +$('#dimension-switch').bootstrapSwitch('setSizeClass', 'switch-large');
      +
      +
      + + + + + + + +
      +
      + Change the colors programmatically: + +
      +
      + + +
      <input type="checkbox" checked data-on="primary" data-off="info">
      +<input type="checkbox" checked data-on="info" data-off="success">
      +<input type="checkbox" checked data-on="success" data-off="warning">
      +<input type="checkbox" checked data-on="warning" data-off="danger">
      +<input type="checkbox" checked data-on="danger" data-off="default">
      +<input type="checkbox" checked data-on="default" data-off="primary">
      +<input type="checkbox" id="change-color-switch" checked data-on="default" data-off="primary">
      +
      $('#change-color-switch').bootstrapSwitch('setOnClass', 'success');
      +$('#change-color-switch').bootstrapSwitch('setOffClass', 'danger');
      +
      +
      + + +
      +
      + + +
      <input type="checkbox" checked data-animated="false">
      +
      // Enables animation for the selected item
      +$('#animated-switch').bootstrapSwitch('setAnimated', true);
      +
      +// Disables animation for the selected item
      +$('#animated-switch').bootstrapSwitch('setAnimated', false);
      +
      +
      + + + +
      <input type="checkbox" checked disabled>
      +<input type="checkbox" checked readonly>
      +
      +
      + + +
      +
      + + +
      <input type="checkbox" checked data-on-label="SI" data-off-label="NO">
      +
      $('#label-switch').bootstrapSwitch('setOnLabel', 'I');
      +$('#label-switch').bootstrapSwitch('setOffLabel', 'O');
      +
      + +
      + +
      +
      <input type="checkbox" checked data-text-label="TV">
      + +
      + +
      +
      <input type="checkbox" checked data-on-label="<i class='icon-ok icon-white'></i>" data-off-label="<i class='icon-remove'></i>">
      + +
      + Standard    + Font Awesome    + Flat UI +
      +
      <input type="checkbox" checked class="switch-large" data-label-icon="icon-fullscreen" data-on-label="<i class='icon-ok icon-white'></i>" data-off-label="<i class='icon-remove'></i>">
      +<input type="checkbox" checked class="switch-large" data-label-icon="icon-youtube icon-large" data-on-label="<i class='icon-thumbs-up icon-white'></i>" data-off-label="<i class='icon-thumbs-down'></i>">
      +<input type="checkbox" class="switch-large" checked data-label-icon="fui-video" data-on-label="<i class='fui-check icon-white'></i>" data-off-label="<i class='fui-cross'></i>">
      + +
      + +
      +
      $('#switch-change').on('switch-change', function (e, data) {
      +  var $element = $(data.el),
      +      value = data.value;
      +
      +  console.log(e, $element, value);
      +});
      + +
      + + +
      +
      <label id="label-toggle-switch">Click on this Text to change the switch state</label>
      +<input type="checkbox" checked>
      +
      $('#label-toggle-switch').on('click', function(e, data) {
      +    $('.label-toggle-switch').bootstrapSwitch('toggleState');
      +});
      +$('.label-toggle-switch').on('switch-change', function (e, data) {
      +    alert(data.value);
      +});
      + +
      + +
      +
      +
      State!
      +
      On
      +
      Toggle
      +
      Off
      +
      +
      $('#toggle-state-switch').bootstrapSwitch('state'); // true || false
      +$('#toggle-state-switch').bootstrapSwitch('toggleState');
      +$('#toggle-state-switch').bootstrapSwitch('setState', false); // true || false
      + +
      + +
      +
      + +
      +
      $('#destroy-switch').bootstrapSwitch('destroy');
      + +
      + +
      +
      +
      Create
      +
      +
      $('#create-switch').bootstrapSwitch();
      + +
      + + +
      +
      + + + + +
      +
      + + +
      +
      + + + + +
      +
      $('#disable-switch').bootstrapSwitch('isDisabled');
      +$('#disable-switch').bootstrapSwitch('toggleDisabled');
      +$('#disable-switch').bootstrapSwitch('setDisabled', true);  // true || false
      +
      +$('#readonly-switch').bootstrapSwitch('isReadOnly');
      +$('#readonly-switch').bootstrapSwitch('toggleReadOnly');
      +$('#readonly-switch').bootstrapSwitch('setReadOnly', true);  // true || false
      + +
      +
      + +    + +    + + +
      +
      +
      <div class="form-group">
      +  <label for="option1">Option 1</label>
      +  <input id="option1" type="radio" name="radio1" value="option1">
      +  <label for="option2">Option 2</label>
      +  <input id="option2" type="radio" name="radio1" value="option2">
      +  <label for="option3">Option 3</label>
      +  <input id="option3" type="radio" name="radio1" value="option3">
      +</div>
      +
      $('.radio1').on('switch-change', function () {
      +    $('.radio1').bootstrapSwitch('toggleRadioState');
      +});
      +
      +// or
      +$('.radio1').on('switch-change', function () {
      +    $('.radio1').bootstrapSwitch('toggleRadioStateAllowUncheck');
      +});
      +
      +// or
      +$('.radio1').on('switch-change', function () {
      +    $('.radio1').bootstrapSwitch('toggleRadioStateAllowUncheck', false);
      +});
      + +
      +
      + + + + + + +
      +
      +
      <div class="form-group">
      +  <label for="option11">Option 1</label>
      +  <input id="option11" type="radio" name="radio2" value="option1">
      +  <label for="option12">Option 2</label>
      +  <input id="option12" type="radio" name="radio2" value="option2" checked="checked">
      +  <label for="option13">Option 3</label>
      +  <input id="option13" type="radio" name="radio2" value="option3">
      +</div>
      +
      $('.radio2').on('switch-change', function () {
      +    $('.radio2').bootstrapSwitch('toggleRadioStateAllowUncheck', true);
      +});
      + +
      +
      +
      + + +
      +
      + + +
      +
      + + +
      +
      + +
      + +
      +
      +
      <form class="form-horizontal">
      +  <div class="form-group">
      +    <label class="control-label" for="inputEmail">Email</label>
      +    <input type="text" id="inputEmail" placeholder="Email">
      +  </div>
      +  <div class="form-group">
      +    <label class="control-label" for="notification1">Notification 1</label>
      +    <input id="notification1" type="checkbox">
      +  </div>
      +  <div class="form-group">
      +    <label class="control-label" for="notification2">Notification 2</label>
      +    <input id="notification2" type="checkbox">
      +  </div>
      +  <div class="form-actions">
      +    <button type="reset" class="btn btn-inverse">Reset</button>
      +  </div>
      +</form>
      + +
      + Modal +
      +
      <a href="#myModal" role="button" class="btn btn-default" data-toggle="modal">Modal</a>
      +
      +<div class="modal-body">
      +  <input type="checkbox" checked>
      +</div>
      + +
      +
      +
      + + + + + + + + diff --git a/dist/bower_components/bootstrap-switch/package.json b/dist/bower_components/bootstrap-switch/package.json new file mode 100644 index 000000000..f9aa5bf09 --- /dev/null +++ b/dist/bower_components/bootstrap-switch/package.json @@ -0,0 +1,55 @@ +{ + "name": "bootstrap-switch", + "description": "Turn checkboxes and radio buttons in toggle switches.", + "version": "2.0.1", + "keywords": [ + "bootstrap", + "switch", + "javascript", + "js" + ], + "homepage": "http://www.bootstrap-switch.org", + "author": { + "name": "Mattia Larentis", + "email": "sorich87@gmail.com", + "url": "http://larentis.eu" + }, + "contributors": [ + { + "name": "Emanuele Marchi", + "email": "emanuele@lostcrew.it", + "url": "http://lostcrew.it" + }, + { + "name": "Peter Stein", + "url": "http://www.bdmdesign.org" + } + ], + "main": "build/js/bootstrap-switch.js", + "dependencies": { + "jquery": ">=1.9.0" + }, + "repository": { + "type": "git", + "url": "git://github.com/nostalgiaz/bootstrap-switch.git" + }, + "bugs": "https://github.com/nostalgiaz/bootstrap-switch/issues", + "license": "Apache Version 2", + "readmeFilename": "README.md", + "devDependencies": { + "matchdep": "~0.3.0", + "grunt": "~0.4.2", + "grunt-contrib-less": "~0.8.3", + "grunt-contrib-jshint": "~0.7.2", + "grunt-bump": "0.0.11", + "grunt-contrib-coffee": "~0.7.0", + "grunt-contrib-uglify": "~0.2.7", + "grunt-contrib-cssmin": "~0.7.0", + "grunt-coffeelint": "0.0.8", + "grunt-banner": "~0.2.0", + "grunt-contrib-watch": "~0.5.3", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-connect": "~0.6.0", + "grunt-open": "~0.2.2" + } +} diff --git a/dist/bower_components/bootstrap-switch/src/coffee/bootstrap-switch.coffee b/dist/bower_components/bootstrap-switch/src/coffee/bootstrap-switch.coffee new file mode 100644 index 000000000..7997ee125 --- /dev/null +++ b/dist/bower_components/bootstrap-switch/src/coffee/bootstrap-switch.coffee @@ -0,0 +1,340 @@ +(($) -> + $.fn.bootstrapSwitch = (method) -> + methods = + init: -> + @each -> + $element = $(@) + $switchLeft = $("", + class: "switch-left" + html: -> + html = "ON" + label = $element.data("on-label") + html = label if label? + html + ) + $switchRight = $("", + class: "switch-right" + html: -> + html = "OFF" + label = $element.data("off-label") + html = label if label? + html + ) + $label = $("\s*$/g,At={option:[1,""],legend:[1,"
      ","
      "],area:[1,"",""],param:[1,"",""],thead:[1,"
      `s and ``s.\n@table-cell-padding: 8px;\n//** Padding for cells in `.table-condensed`.\n@table-condensed-cell-padding: 5px;\n\n//** Default background color used for all tables.\n@table-bg: transparent;\n//** Background color used for `.table-striped`.\n@table-bg-accent: #f9f9f9;\n//** Background color used for `.table-hover`.\n@table-bg-hover: #f5f5f5;\n@table-bg-active: @table-bg-hover;\n\n//** Border color for table and cell borders.\n@table-border-color: #ddd;\n\n\n//== Buttons\n//\n//## For each of Bootstrap's buttons, define text, background and border color.\n\n@btn-font-weight: normal;\n\n@btn-default-color: #333;\n@btn-default-bg: #fff;\n@btn-default-border: #ccc;\n\n@btn-primary-color: #fff;\n@btn-primary-bg: @brand-primary;\n@btn-primary-border: darken(@btn-primary-bg, 5%);\n\n@btn-success-color: #fff;\n@btn-success-bg: @brand-success;\n@btn-success-border: darken(@btn-success-bg, 5%);\n\n@btn-info-color: #fff;\n@btn-info-bg: @brand-info;\n@btn-info-border: darken(@btn-info-bg, 5%);\n\n@btn-warning-color: #fff;\n@btn-warning-bg: @brand-warning;\n@btn-warning-border: darken(@btn-warning-bg, 5%);\n\n@btn-danger-color: #fff;\n@btn-danger-bg: @brand-danger;\n@btn-danger-border: darken(@btn-danger-bg, 5%);\n\n@btn-link-disabled-color: @gray-light;\n\n\n//== Forms\n//\n//##\n\n//** `` background color\n@input-bg: #fff;\n//** `` background color\n@input-bg-disabled: @gray-lighter;\n\n//** Text color for ``s\n@input-color: @gray;\n//** `` border color\n@input-border: #ccc;\n//** `` border radius\n@input-border-radius: @border-radius-base;\n//** Border color for inputs on focus\n@input-border-focus: #66afe9;\n\n//** Placeholder text color\n@input-color-placeholder: @gray-light;\n\n//** Default `.form-control` height\n@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);\n//** Large `.form-control` height\n@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\n//** Small `.form-control` height\n@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);\n\n@legend-color: @gray-dark;\n@legend-border-color: #e5e5e5;\n\n//** Background color for textual input addons\n@input-group-addon-bg: @gray-lighter;\n//** Border color for textual input addons\n@input-group-addon-border-color: @input-border;\n\n\n//== Dropdowns\n//\n//## Dropdown menu container and contents.\n\n//** Background for the dropdown menu.\n@dropdown-bg: #fff;\n//** Dropdown menu `border-color`.\n@dropdown-border: rgba(0,0,0,.15);\n//** Dropdown menu `border-color` **for IE8**.\n@dropdown-fallback-border: #ccc;\n//** Divider color for between dropdown items.\n@dropdown-divider-bg: #e5e5e5;\n\n//** Dropdown link text color.\n@dropdown-link-color: @gray-dark;\n//** Hover color for dropdown links.\n@dropdown-link-hover-color: darken(@gray-dark, 5%);\n//** Hover background for dropdown links.\n@dropdown-link-hover-bg: #f5f5f5;\n\n//** Active dropdown menu item text color.\n@dropdown-link-active-color: @component-active-color;\n//** Active dropdown menu item background color.\n@dropdown-link-active-bg: @component-active-bg;\n\n//** Disabled dropdown menu item background color.\n@dropdown-link-disabled-color: @gray-light;\n\n//** Text color for headers within dropdown menus.\n@dropdown-header-color: @gray-light;\n\n// Note: Deprecated @dropdown-caret-color as of v3.1.0\n@dropdown-caret-color: #000;\n\n\n//-- Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n//\n// Note: These variables are not generated into the Customizer.\n\n@zindex-navbar: 1000;\n@zindex-dropdown: 1000;\n@zindex-popover: 1010;\n@zindex-tooltip: 1030;\n@zindex-navbar-fixed: 1030;\n@zindex-modal-background: 1040;\n@zindex-modal: 1050;\n\n\n//== Media queries breakpoints\n//\n//## Define the breakpoints at which your layout will change, adapting to different screen sizes.\n\n// Extra small screen / phone\n// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1\n@screen-xs: 480px;\n@screen-xs-min: @screen-xs;\n@screen-phone: @screen-xs-min;\n\n// Small screen / tablet\n// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1\n@screen-sm: 768px;\n@screen-sm-min: @screen-sm;\n@screen-tablet: @screen-sm-min;\n\n// Medium screen / desktop\n// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1\n@screen-md: 992px;\n@screen-md-min: @screen-md;\n@screen-desktop: @screen-md-min;\n\n// Large screen / wide desktop\n// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1\n@screen-lg: 1200px;\n@screen-lg-min: @screen-lg;\n@screen-lg-desktop: @screen-lg-min;\n\n// So media queries don't overlap when required, provide a maximum\n@screen-xs-max: (@screen-sm-min - 1);\n@screen-sm-max: (@screen-md-min - 1);\n@screen-md-max: (@screen-lg-min - 1);\n\n\n//== Grid system\n//\n//## Define your custom responsive grid.\n\n//** Number of columns in the grid.\n@grid-columns: 12;\n//** Padding between columns. Gets divided in half for the left and right.\n@grid-gutter-width: 30px;\n// Navbar collapse\n//** Point at which the navbar becomes uncollapsed.\n@grid-float-breakpoint: @screen-sm-min;\n//** Point at which the navbar begins collapsing.\n@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);\n\n\n//== Navbar\n//\n//##\n\n// Basics of a navbar\n@navbar-height: 50px;\n@navbar-margin-bottom: @line-height-computed;\n@navbar-border-radius: @border-radius-base;\n@navbar-padding-horizontal: floor((@grid-gutter-width / 2));\n@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);\n@navbar-collapse-max-height: 340px;\n\n@navbar-default-color: #777;\n@navbar-default-bg: #f8f8f8;\n@navbar-default-border: darken(@navbar-default-bg, 6.5%);\n\n// Navbar links\n@navbar-default-link-color: #777;\n@navbar-default-link-hover-color: #333;\n@navbar-default-link-hover-bg: transparent;\n@navbar-default-link-active-color: #555;\n@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);\n@navbar-default-link-disabled-color: #ccc;\n@navbar-default-link-disabled-bg: transparent;\n\n// Navbar brand label\n@navbar-default-brand-color: @navbar-default-link-color;\n@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%);\n@navbar-default-brand-hover-bg: transparent;\n\n// Navbar toggle\n@navbar-default-toggle-hover-bg: #ddd;\n@navbar-default-toggle-icon-bar-bg: #888;\n@navbar-default-toggle-border-color: #ddd;\n\n\n// Inverted navbar\n// Reset inverted navbar basics\n@navbar-inverse-color: @gray-light;\n@navbar-inverse-bg: #222;\n@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);\n\n// Inverted navbar links\n@navbar-inverse-link-color: @gray-light;\n@navbar-inverse-link-hover-color: #fff;\n@navbar-inverse-link-hover-bg: transparent;\n@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;\n@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);\n@navbar-inverse-link-disabled-color: #444;\n@navbar-inverse-link-disabled-bg: transparent;\n\n// Inverted navbar brand label\n@navbar-inverse-brand-color: @navbar-inverse-link-color;\n@navbar-inverse-brand-hover-color: #fff;\n@navbar-inverse-brand-hover-bg: transparent;\n\n// Inverted navbar toggle\n@navbar-inverse-toggle-hover-bg: #333;\n@navbar-inverse-toggle-icon-bar-bg: #fff;\n@navbar-inverse-toggle-border-color: #333;\n\n\n//== Navs\n//\n//##\n\n//=== Shared nav styles\n@nav-link-padding: 10px 15px;\n@nav-link-hover-bg: @gray-lighter;\n\n@nav-disabled-link-color: @gray-light;\n@nav-disabled-link-hover-color: @gray-light;\n\n@nav-open-link-hover-color: #fff;\n\n//== Tabs\n@nav-tabs-border-color: #ddd;\n\n@nav-tabs-link-hover-border-color: @gray-lighter;\n\n@nav-tabs-active-link-hover-bg: @body-bg;\n@nav-tabs-active-link-hover-color: @gray;\n@nav-tabs-active-link-hover-border-color: #ddd;\n\n@nav-tabs-justified-link-border-color: #ddd;\n@nav-tabs-justified-active-link-border-color: @body-bg;\n\n//== Pills\n@nav-pills-border-radius: @border-radius-base;\n@nav-pills-active-link-hover-bg: @component-active-bg;\n@nav-pills-active-link-hover-color: @component-active-color;\n\n\n//== Pagination\n//\n//##\n\n@pagination-color: @link-color;\n@pagination-bg: #fff;\n@pagination-border: #ddd;\n\n@pagination-hover-color: @link-hover-color;\n@pagination-hover-bg: @gray-lighter;\n@pagination-hover-border: #ddd;\n\n@pagination-active-color: #fff;\n@pagination-active-bg: @brand-primary;\n@pagination-active-border: @brand-primary;\n\n@pagination-disabled-color: @gray-light;\n@pagination-disabled-bg: #fff;\n@pagination-disabled-border: #ddd;\n\n\n//== Pager\n//\n//##\n\n@pager-bg: @pagination-bg;\n@pager-border: @pagination-border;\n@pager-border-radius: 15px;\n\n@pager-hover-bg: @pagination-hover-bg;\n\n@pager-active-bg: @pagination-active-bg;\n@pager-active-color: @pagination-active-color;\n\n@pager-disabled-color: @pagination-disabled-color;\n\n\n//== Jumbotron\n//\n//##\n\n@jumbotron-padding: 30px;\n@jumbotron-color: inherit;\n@jumbotron-bg: @gray-lighter;\n@jumbotron-heading-color: inherit;\n@jumbotron-font-size: ceil((@font-size-base * 1.5));\n\n\n//== Form states and alerts\n//\n//## Define colors for form feedback states and, by default, alerts.\n\n@state-success-text: #3c763d;\n@state-success-bg: #dff0d8;\n@state-success-border: darken(spin(@state-success-bg, -10), 5%);\n\n@state-info-text: #31708f;\n@state-info-bg: #d9edf7;\n@state-info-border: darken(spin(@state-info-bg, -10), 7%);\n\n@state-warning-text: #8a6d3b;\n@state-warning-bg: #fcf8e3;\n@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);\n\n@state-danger-text: #a94442;\n@state-danger-bg: #f2dede;\n@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);\n\n\n//== Tooltips\n//\n//##\n\n//** Tooltip max width\n@tooltip-max-width: 200px;\n//** Tooltip text color\n@tooltip-color: #fff;\n//** Tooltip background color\n@tooltip-bg: #000;\n@tooltip-opacity: .9;\n\n//** Tooltip arrow width\n@tooltip-arrow-width: 5px;\n//** Tooltip arrow color\n@tooltip-arrow-color: @tooltip-bg;\n\n\n//== Popovers\n//\n//##\n\n//** Popover body background color\n@popover-bg: #fff;\n//** Popover maximum width\n@popover-max-width: 276px;\n//** Popover border color\n@popover-border-color: rgba(0,0,0,.2);\n//** Popover fallback border color\n@popover-fallback-border-color: #ccc;\n\n//** Popover title background color\n@popover-title-bg: darken(@popover-bg, 3%);\n\n//** Popover arrow width\n@popover-arrow-width: 10px;\n//** Popover arrow color\n@popover-arrow-color: #fff;\n\n//** Popover outer arrow width\n@popover-arrow-outer-width: (@popover-arrow-width + 1);\n//** Popover outer arrow color\n@popover-arrow-outer-color: rgba(0,0,0,.25);\n//** Popover outer arrow fallback color\n@popover-arrow-outer-fallback-color: #999;\n\n\n//== Labels\n//\n//##\n\n//** Default label background color\n@label-default-bg: @gray-light;\n//** Primary label background color\n@label-primary-bg: @brand-primary;\n//** Success label background color\n@label-success-bg: @brand-success;\n//** Info label background color\n@label-info-bg: @brand-info;\n//** Warning label background color\n@label-warning-bg: @brand-warning;\n//** Danger label background color\n@label-danger-bg: @brand-danger;\n\n//** Default label text color\n@label-color: #fff;\n//** Default text color of a linked label\n@label-link-hover-color: #fff;\n\n\n//== Modals\n//\n//##\n\n//** Padding applied to the modal body\n@modal-inner-padding: 20px;\n\n//** Padding applied to the modal title\n@modal-title-padding: 15px;\n//** Modal title line-height\n@modal-title-line-height: @line-height-base;\n\n//** Background color of modal content area\n@modal-content-bg: #fff;\n//** Modal content border color\n@modal-content-border-color: rgba(0,0,0,.2);\n//** Modal content border color **for IE8**\n@modal-content-fallback-border-color: #999;\n\n//** Modal backdrop background color\n@modal-backdrop-bg: #000;\n//** Modal backdrop opacity\n@modal-backdrop-opacity: .5;\n//** Modal header border color\n@modal-header-border-color: #e5e5e5;\n//** Modal footer border color\n@modal-footer-border-color: @modal-header-border-color;\n\n@modal-lg: 900px;\n@modal-md: 600px;\n@modal-sm: 300px;\n\n\n//== Alerts\n//\n//## Define alert colors, border radius, and padding.\n\n@alert-padding: 15px;\n@alert-border-radius: @border-radius-base;\n@alert-link-font-weight: bold;\n\n@alert-success-bg: @state-success-bg;\n@alert-success-text: @state-success-text;\n@alert-success-border: @state-success-border;\n\n@alert-info-bg: @state-info-bg;\n@alert-info-text: @state-info-text;\n@alert-info-border: @state-info-border;\n\n@alert-warning-bg: @state-warning-bg;\n@alert-warning-text: @state-warning-text;\n@alert-warning-border: @state-warning-border;\n\n@alert-danger-bg: @state-danger-bg;\n@alert-danger-text: @state-danger-text;\n@alert-danger-border: @state-danger-border;\n\n\n//== Progress bars\n//\n//##\n\n//** Background color of the whole progress component\n@progress-bg: #f5f5f5;\n//** Progress bar text color\n@progress-bar-color: #fff;\n\n//** Default progress bar color\n@progress-bar-bg: @brand-primary;\n//** Success progress bar color\n@progress-bar-success-bg: @brand-success;\n//** Warning progress bar color\n@progress-bar-warning-bg: @brand-warning;\n//** Danger progress bar color\n@progress-bar-danger-bg: @brand-danger;\n//** Info progress bar color\n@progress-bar-info-bg: @brand-info;\n\n\n//== List group\n//\n//##\n\n//** Background color on `.list-group-item`\n@list-group-bg: #fff;\n//** `.list-group-item` border color\n@list-group-border: #ddd;\n//** List group border radius\n@list-group-border-radius: @border-radius-base;\n\n//** Background color of single list elements on hover\n@list-group-hover-bg: #f5f5f5;\n//** Text color of active list elements\n@list-group-active-color: @component-active-color;\n//** Background color of active list elements\n@list-group-active-bg: @component-active-bg;\n//** Border color of active list elements\n@list-group-active-border: @list-group-active-bg;\n@list-group-active-text-color: lighten(@list-group-active-bg, 40%);\n\n@list-group-link-color: #555;\n@list-group-link-heading-color: #333;\n\n\n//== Panels\n//\n//##\n\n@panel-bg: #fff;\n@panel-body-padding: 15px;\n@panel-border-radius: @border-radius-base;\n\n//** Border color for elements within panels\n@panel-inner-border: #ddd;\n@panel-footer-bg: #f5f5f5;\n\n@panel-default-text: @gray-dark;\n@panel-default-border: #ddd;\n@panel-default-heading-bg: #f5f5f5;\n\n@panel-primary-text: #fff;\n@panel-primary-border: @brand-primary;\n@panel-primary-heading-bg: @brand-primary;\n\n@panel-success-text: @state-success-text;\n@panel-success-border: @state-success-border;\n@panel-success-heading-bg: @state-success-bg;\n\n@panel-info-text: @state-info-text;\n@panel-info-border: @state-info-border;\n@panel-info-heading-bg: @state-info-bg;\n\n@panel-warning-text: @state-warning-text;\n@panel-warning-border: @state-warning-border;\n@panel-warning-heading-bg: @state-warning-bg;\n\n@panel-danger-text: @state-danger-text;\n@panel-danger-border: @state-danger-border;\n@panel-danger-heading-bg: @state-danger-bg;\n\n\n//== Thumbnails\n//\n//##\n\n//** Padding around the thumbnail image\n@thumbnail-padding: 4px;\n//** Thumbnail background color\n@thumbnail-bg: @body-bg;\n//** Thumbnail border color\n@thumbnail-border: #ddd;\n//** Thumbnail border radius\n@thumbnail-border-radius: @border-radius-base;\n\n//** Custom text color for thumbnail captions\n@thumbnail-caption-color: @text-color;\n//** Padding around the thumbnail caption\n@thumbnail-caption-padding: 9px;\n\n\n//== Wells\n//\n//##\n\n@well-bg: #f5f5f5;\n@well-border: darken(@well-bg, 7%);\n\n\n//== Badges\n//\n//##\n\n@badge-color: #fff;\n//** Linked badge text color on hover\n@badge-link-hover-color: #fff;\n@badge-bg: @gray-light;\n\n//** Badge text color in active nav link\n@badge-active-color: @link-color;\n//** Badge background color in active nav link\n@badge-active-bg: #fff;\n\n@badge-font-weight: bold;\n@badge-line-height: 1;\n@badge-border-radius: 10px;\n\n\n//== Breadcrumbs\n//\n//##\n\n@breadcrumb-padding-vertical: 8px;\n@breadcrumb-padding-horizontal: 15px;\n//** Breadcrumb background color\n@breadcrumb-bg: #f5f5f5;\n//** Breadcrumb text color\n@breadcrumb-color: #ccc;\n//** Text color of current page in the breadcrumb\n@breadcrumb-active-color: @gray-light;\n//** Textual separator for between breadcrumb elements\n@breadcrumb-separator: \"/\";\n\n\n//== Carousel\n//\n//##\n\n@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);\n\n@carousel-control-color: #fff;\n@carousel-control-width: 15%;\n@carousel-control-opacity: .5;\n@carousel-control-font-size: 20px;\n\n@carousel-indicator-active-bg: #fff;\n@carousel-indicator-border-color: #fff;\n\n@carousel-caption-color: #fff;\n\n\n//== Close\n//\n//##\n\n@close-font-weight: bold;\n@close-color: #000;\n@close-text-shadow: 0 1px 0 #fff;\n\n\n//== Code\n//\n//##\n\n@code-color: #c7254e;\n@code-bg: #f9f2f4;\n\n@kbd-color: #fff;\n@kbd-bg: #333;\n\n@pre-bg: #f5f5f5;\n@pre-color: @gray-dark;\n@pre-border-color: #ccc;\n@pre-scrollable-max-height: 340px;\n\n\n//== Type\n//\n//##\n\n//** Text muted color\n@text-muted: @gray-light;\n//** Abbreviations and acronyms border color\n@abbr-border-color: @gray-light;\n//** Headings small color\n@headings-small-color: @gray-light;\n//** Blockquote small color\n@blockquote-small-color: @gray-light;\n//** Blockquote border color\n@blockquote-border-color: @gray-lighter;\n//** Page header border color\n@page-header-border-color: @gray-lighter;\n\n\n//== Miscellaneous\n//\n//##\n\n//** Horizontal line color.\n@hr-border: @gray-lighter;\n\n//** Horizontal offset for forms and lists.\n@component-offset-horizontal: 180px;\n\n\n//== Container sizes\n//\n//## Define the maximum width of `.container` for different screen sizes.\n\n// Small screen / tablet\n@container-tablet: ((720px + @grid-gutter-width));\n//** For `@screen-sm-min` and up.\n@container-sm: @container-tablet;\n\n// Medium screen / desktop\n@container-desktop: ((940px + @grid-gutter-width));\n//** For `@screen-md-min` and up.\n@container-md: @container-desktop;\n\n// Large screen / wide desktop\n@container-large-desktop: ((1140px + @grid-gutter-width));\n//** For `@screen-lg-min` and up.\n@container-lg: @container-large-desktop;\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 200;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: 14px base font * 85% = about 12px\nsmall,\n.small { font-size: 85%; }\n\n// Undo browser default styling\ncite { font-style: normal; }\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// --------------------------------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n\n &:first-child {\n padding-left: 0;\n }\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n@media (min-width: @grid-float-breakpoint) {\n .dl-horizontal {\n dt {\n float: left;\n width: (@component-offset-horizontal - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @component-offset-horizontal;\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n }\n}\n\n// MISC\n// ----\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: (@font-size-base * 1.25);\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n content: \"\";\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n white-space: nowrap;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid-columns-float(xs);\n.make-grid(@grid-columns, xs, width);\n.make-grid(@grid-columns, xs, pull);\n.make-grid(@grid-columns, xs, push);\n.make-grid(@grid-columns, xs, offset);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid-columns-float(sm);\n .make-grid(@grid-columns, sm, width);\n .make-grid(@grid-columns, sm, pull);\n .make-grid(@grid-columns, sm, push);\n .make-grid(@grid-columns, sm, offset);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid-columns-float(md);\n .make-grid(@grid-columns, md, width);\n .make-grid(@grid-columns, md, pull);\n .make-grid(@grid-columns, md, push);\n .make-grid(@grid-columns, md, offset);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid-columns-float(lg);\n .make-grid(@grid-columns, lg, width);\n .make-grid(@grid-columns, lg, pull);\n .make-grid(@grid-columns, lg, push);\n .make-grid(@grid-columns, lg, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n max-width: 100%;\n background-color: @table-bg;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-child(odd) {\n > td,\n > th {\n background-color: @table-bg-accent;\n }\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n > td,\n > th {\n background-color: @table-bg-hover;\n }\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n@media (max-width: @screen-xs-max) {\n .table-responsive {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n overflow-x: scroll;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n -webkit-overflow-scrolling: touch;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: -webkit-min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; /* IE8-9 */\n line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n // Note: HTML5 says that controls under a fieldset > legend:first-child won't\n // be disabled if the fieldset is disabled. Due to implementation difficulty,\n // we don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n cursor: not-allowed;\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n// Special styles for iOS date input\n//\n// In Mobile Safari, date inputs require a pixel line-height that matches the\n// given height of the input.\ninput[type=\"date\"] {\n line-height: @input-height-base;\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n display: block;\n min-height: @line-height-computed; // clear the floating input if there is no label text\n margin-top: 10px;\n margin-bottom: 10px;\n padding-left: 20px;\n label {\n display: inline;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n float: left;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"],\n.radio,\n.radio-inline,\n.checkbox,\n.checkbox-inline {\n &[disabled],\n fieldset[disabled] & {\n cursor: not-allowed;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\n.input-sm {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.input-lg {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n\n // Feedback icon (requires .glyphicon classes)\n .form-control-feedback {\n position: absolute;\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n right: 0;\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n }\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n margin-bottom: 0; // Remove default margin from `p`\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n display: block; // account for any element using help-block\n margin-top: 5px;\n margin-bottom: 10px;\n color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n // Kick in the inline\n @media (min-width: @screen-sm-min) {\n // Inline-block all the things for \"inline\"\n .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // In navbar-form, allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match (which also avoids\n // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n .radio,\n .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n vertical-align: middle;\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n float: none;\n margin-left: 0;\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n }\n }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n // Consistent vertical alignment of labels, radios, and checkboxes\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n .form-control-static {\n padding-top: (@padding-base-vertical + 1);\n }\n\n // Only right align form labels here when the columns stop stacking\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n right: (@grid-gutter-width / 2);\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n .user-select(none);\n\n &:focus {\n .tab-focus();\n }\n\n &:hover,\n &:focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: not-allowed;\n pointer-events: none; // Future-proof disabling of clicks\n .opacity(.65);\n .box-shadow(none);\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n cursor: pointer;\n border-radius: 0;\n\n &,\n &:active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: underline;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n padding-left: 0;\n padding-right: 0;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n &.in {\n display: block;\n }\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition(height .35s ease);\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: ~\"url('@{icon-font-path}@{icon-font-name}.eot')\";\n src: ~\"url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.woff') format('woff')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg')\";\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base solid;\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: not-allowed;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base solid;\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 1px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n &:focus {\n // Remove focus outline when dropdown JS adds it after closing the menu\n outline: none;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { .btn-xs(); }\n.btn-group-sm > .btn { .btn-sm(); }\n.btn-group-lg > .btn { .btn-lg(); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n border-top-right-radius: @border-radius-base;\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n border-bottom-left-radius: @border-radius-base;\n .border-top-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n}\n\n\n// Checkbox and radio options\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n display: none;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn { .input-lg(); }\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn { .input-sm(); }\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @border-radius-base;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n max-height: @navbar-collapse-max-height;\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @line-height-computed;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: none;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right { .pull-right(); }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: 0;\n }\n }\n}\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: not-allowed;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: not-allowed;\n }\n }\n\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n &[href] {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base classes\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: baseline;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n .btn-xs & {\n top: 0;\n padding: 1px 5px;\n }\n}\n\n// Hover state, but only for links\na.badge {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n}\n\n// Account for counters in navs\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n .container & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: (@font-size-base * 4.5);\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n > img,\n a > img {\n .img-responsive();\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissable alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n.progress-striped .progress-bar {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n.progress.active .progress-bar {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n > .pull-left {\n margin-right: 10px;\n }\n > .pull-right {\n margin-left: 10px;\n }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on `s and ``s. +@table-cell-padding: 8px; +//** Padding for cells in `.table-condensed`. +@table-condensed-cell-padding: 5px; + +//** Default background color used for all tables. +@table-bg: transparent; +//** Background color used for `.table-striped`. +@table-bg-accent: #f9f9f9; +//** Background color used for `.table-hover`. +@table-bg-hover: #f5f5f5; +@table-bg-active: @table-bg-hover; + +//** Border color for table and cell borders. +@table-border-color: #ddd; + + +//== Buttons +// +//## For each of Bootstrap's buttons, define text, background and border color. + +@btn-font-weight: normal; + +@btn-default-color: #333; +@btn-default-bg: #fff; +@btn-default-border: #ccc; + +@btn-primary-color: #fff; +@btn-primary-bg: @brand-primary; +@btn-primary-border: darken(@btn-primary-bg, 5%); + +@btn-success-color: #fff; +@btn-success-bg: @brand-success; +@btn-success-border: darken(@btn-success-bg, 5%); + +@btn-info-color: #fff; +@btn-info-bg: @brand-info; +@btn-info-border: darken(@btn-info-bg, 5%); + +@btn-warning-color: #fff; +@btn-warning-bg: @brand-warning; +@btn-warning-border: darken(@btn-warning-bg, 5%); + +@btn-danger-color: #fff; +@btn-danger-bg: @brand-danger; +@btn-danger-border: darken(@btn-danger-bg, 5%); + +@btn-link-disabled-color: @gray-light; + + +//== Forms +// +//## + +//** `` background color +@input-bg: #fff; +//** `` background color +@input-bg-disabled: @gray-lighter; + +//** Text color for ``s +@input-color: @gray; +//** `` border color +@input-border: #ccc; +//** `` border radius +@input-border-radius: @border-radius-base; +//** Border color for inputs on focus +@input-border-focus: #66afe9; + +//** Placeholder text color +@input-color-placeholder: @gray-light; + +//** Default `.form-control` height +@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2); +//** Large `.form-control` height +@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2); +//** Small `.form-control` height +@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2); + +@legend-color: @gray-dark; +@legend-border-color: #e5e5e5; + +//** Background color for textual input addons +@input-group-addon-bg: @gray-lighter; +//** Border color for textual input addons +@input-group-addon-border-color: @input-border; + + +//== Dropdowns +// +//## Dropdown menu container and contents. + +//** Background for the dropdown menu. +@dropdown-bg: #fff; +//** Dropdown menu `border-color`. +@dropdown-border: rgba(0,0,0,.15); +//** Dropdown menu `border-color` **for IE8**. +@dropdown-fallback-border: #ccc; +//** Divider color for between dropdown items. +@dropdown-divider-bg: #e5e5e5; + +//** Dropdown link text color. +@dropdown-link-color: @gray-dark; +//** Hover color for dropdown links. +@dropdown-link-hover-color: darken(@gray-dark, 5%); +//** Hover background for dropdown links. +@dropdown-link-hover-bg: #f5f5f5; + +//** Active dropdown menu item text color. +@dropdown-link-active-color: @component-active-color; +//** Active dropdown menu item background color. +@dropdown-link-active-bg: @component-active-bg; + +//** Disabled dropdown menu item background color. +@dropdown-link-disabled-color: @gray-light; + +//** Text color for headers within dropdown menus. +@dropdown-header-color: @gray-light; + +// Note: Deprecated @dropdown-caret-color as of v3.1.0 +@dropdown-caret-color: #000; + + +//-- Z-index master list +// +// Warning: Avoid customizing these values. They're used for a bird's eye view +// of components dependent on the z-axis and are designed to all work together. +// +// Note: These variables are not generated into the Customizer. + +@zindex-navbar: 1000; +@zindex-dropdown: 1000; +@zindex-popover: 1010; +@zindex-tooltip: 1030; +@zindex-navbar-fixed: 1030; +@zindex-modal-background: 1040; +@zindex-modal: 1050; + + +//== Media queries breakpoints +// +//## Define the breakpoints at which your layout will change, adapting to different screen sizes. + +// Extra small screen / phone +// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1 +@screen-xs: 480px; +@screen-xs-min: @screen-xs; +@screen-phone: @screen-xs-min; + +// Small screen / tablet +// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1 +@screen-sm: 768px; +@screen-sm-min: @screen-sm; +@screen-tablet: @screen-sm-min; + +// Medium screen / desktop +// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1 +@screen-md: 992px; +@screen-md-min: @screen-md; +@screen-desktop: @screen-md-min; + +// Large screen / wide desktop +// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1 +@screen-lg: 1200px; +@screen-lg-min: @screen-lg; +@screen-lg-desktop: @screen-lg-min; + +// So media queries don't overlap when required, provide a maximum +@screen-xs-max: (@screen-sm-min - 1); +@screen-sm-max: (@screen-md-min - 1); +@screen-md-max: (@screen-lg-min - 1); + + +//== Grid system +// +//## Define your custom responsive grid. + +//** Number of columns in the grid. +@grid-columns: 12; +//** Padding between columns. Gets divided in half for the left and right. +@grid-gutter-width: 30px; +// Navbar collapse +//** Point at which the navbar becomes uncollapsed. +@grid-float-breakpoint: @screen-sm-min; +//** Point at which the navbar begins collapsing. +@grid-float-breakpoint-max: (@grid-float-breakpoint - 1); + + +//== Navbar +// +//## + +// Basics of a navbar +@navbar-height: 50px; +@navbar-margin-bottom: @line-height-computed; +@navbar-border-radius: @border-radius-base; +@navbar-padding-horizontal: floor((@grid-gutter-width / 2)); +@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2); +@navbar-collapse-max-height: 340px; + +@navbar-default-color: #777; +@navbar-default-bg: #f8f8f8; +@navbar-default-border: darken(@navbar-default-bg, 6.5%); + +// Navbar links +@navbar-default-link-color: #777; +@navbar-default-link-hover-color: #333; +@navbar-default-link-hover-bg: transparent; +@navbar-default-link-active-color: #555; +@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%); +@navbar-default-link-disabled-color: #ccc; +@navbar-default-link-disabled-bg: transparent; + +// Navbar brand label +@navbar-default-brand-color: @navbar-default-link-color; +@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%); +@navbar-default-brand-hover-bg: transparent; + +// Navbar toggle +@navbar-default-toggle-hover-bg: #ddd; +@navbar-default-toggle-icon-bar-bg: #888; +@navbar-default-toggle-border-color: #ddd; + + +// Inverted navbar +// Reset inverted navbar basics +@navbar-inverse-color: @gray-light; +@navbar-inverse-bg: #222; +@navbar-inverse-border: darken(@navbar-inverse-bg, 10%); + +// Inverted navbar links +@navbar-inverse-link-color: @gray-light; +@navbar-inverse-link-hover-color: #fff; +@navbar-inverse-link-hover-bg: transparent; +@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color; +@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%); +@navbar-inverse-link-disabled-color: #444; +@navbar-inverse-link-disabled-bg: transparent; + +// Inverted navbar brand label +@navbar-inverse-brand-color: @navbar-inverse-link-color; +@navbar-inverse-brand-hover-color: #fff; +@navbar-inverse-brand-hover-bg: transparent; + +// Inverted navbar toggle +@navbar-inverse-toggle-hover-bg: #333; +@navbar-inverse-toggle-icon-bar-bg: #fff; +@navbar-inverse-toggle-border-color: #333; + + +//== Navs +// +//## + +//=== Shared nav styles +@nav-link-padding: 10px 15px; +@nav-link-hover-bg: @gray-lighter; + +@nav-disabled-link-color: @gray-light; +@nav-disabled-link-hover-color: @gray-light; + +@nav-open-link-hover-color: #fff; + +//== Tabs +@nav-tabs-border-color: #ddd; + +@nav-tabs-link-hover-border-color: @gray-lighter; + +@nav-tabs-active-link-hover-bg: @body-bg; +@nav-tabs-active-link-hover-color: @gray; +@nav-tabs-active-link-hover-border-color: #ddd; + +@nav-tabs-justified-link-border-color: #ddd; +@nav-tabs-justified-active-link-border-color: @body-bg; + +//== Pills +@nav-pills-border-radius: @border-radius-base; +@nav-pills-active-link-hover-bg: @component-active-bg; +@nav-pills-active-link-hover-color: @component-active-color; + + +//== Pagination +// +//## + +@pagination-color: @link-color; +@pagination-bg: #fff; +@pagination-border: #ddd; + +@pagination-hover-color: @link-hover-color; +@pagination-hover-bg: @gray-lighter; +@pagination-hover-border: #ddd; + +@pagination-active-color: #fff; +@pagination-active-bg: @brand-primary; +@pagination-active-border: @brand-primary; + +@pagination-disabled-color: @gray-light; +@pagination-disabled-bg: #fff; +@pagination-disabled-border: #ddd; + + +//== Pager +// +//## + +@pager-bg: @pagination-bg; +@pager-border: @pagination-border; +@pager-border-radius: 15px; + +@pager-hover-bg: @pagination-hover-bg; + +@pager-active-bg: @pagination-active-bg; +@pager-active-color: @pagination-active-color; + +@pager-disabled-color: @pagination-disabled-color; + + +//== Jumbotron +// +//## + +@jumbotron-padding: 30px; +@jumbotron-color: inherit; +@jumbotron-bg: @gray-lighter; +@jumbotron-heading-color: inherit; +@jumbotron-font-size: ceil((@font-size-base * 1.5)); + + +//== Form states and alerts +// +//## Define colors for form feedback states and, by default, alerts. + +@state-success-text: #3c763d; +@state-success-bg: #dff0d8; +@state-success-border: darken(spin(@state-success-bg, -10), 5%); + +@state-info-text: #31708f; +@state-info-bg: #d9edf7; +@state-info-border: darken(spin(@state-info-bg, -10), 7%); + +@state-warning-text: #8a6d3b; +@state-warning-bg: #fcf8e3; +@state-warning-border: darken(spin(@state-warning-bg, -10), 5%); + +@state-danger-text: #a94442; +@state-danger-bg: #f2dede; +@state-danger-border: darken(spin(@state-danger-bg, -10), 5%); + + +//== Tooltips +// +//## + +//** Tooltip max width +@tooltip-max-width: 200px; +//** Tooltip text color +@tooltip-color: #fff; +//** Tooltip background color +@tooltip-bg: #000; +@tooltip-opacity: .9; + +//** Tooltip arrow width +@tooltip-arrow-width: 5px; +//** Tooltip arrow color +@tooltip-arrow-color: @tooltip-bg; + + +//== Popovers +// +//## + +//** Popover body background color +@popover-bg: #fff; +//** Popover maximum width +@popover-max-width: 276px; +//** Popover border color +@popover-border-color: rgba(0,0,0,.2); +//** Popover fallback border color +@popover-fallback-border-color: #ccc; + +//** Popover title background color +@popover-title-bg: darken(@popover-bg, 3%); + +//** Popover arrow width +@popover-arrow-width: 10px; +//** Popover arrow color +@popover-arrow-color: #fff; + +//** Popover outer arrow width +@popover-arrow-outer-width: (@popover-arrow-width + 1); +//** Popover outer arrow color +@popover-arrow-outer-color: rgba(0,0,0,.25); +//** Popover outer arrow fallback color +@popover-arrow-outer-fallback-color: #999; + + +//== Labels +// +//## + +//** Default label background color +@label-default-bg: @gray-light; +//** Primary label background color +@label-primary-bg: @brand-primary; +//** Success label background color +@label-success-bg: @brand-success; +//** Info label background color +@label-info-bg: @brand-info; +//** Warning label background color +@label-warning-bg: @brand-warning; +//** Danger label background color +@label-danger-bg: @brand-danger; + +//** Default label text color +@label-color: #fff; +//** Default text color of a linked label +@label-link-hover-color: #fff; + + +//== Modals +// +//## + +//** Padding applied to the modal body +@modal-inner-padding: 20px; + +//** Padding applied to the modal title +@modal-title-padding: 15px; +//** Modal title line-height +@modal-title-line-height: @line-height-base; + +//** Background color of modal content area +@modal-content-bg: #fff; +//** Modal content border color +@modal-content-border-color: rgba(0,0,0,.2); +//** Modal content border color **for IE8** +@modal-content-fallback-border-color: #999; + +//** Modal backdrop background color +@modal-backdrop-bg: #000; +//** Modal backdrop opacity +@modal-backdrop-opacity: .5; +//** Modal header border color +@modal-header-border-color: #e5e5e5; +//** Modal footer border color +@modal-footer-border-color: @modal-header-border-color; + +@modal-lg: 900px; +@modal-md: 600px; +@modal-sm: 300px; + + +//== Alerts +// +//## Define alert colors, border radius, and padding. + +@alert-padding: 15px; +@alert-border-radius: @border-radius-base; +@alert-link-font-weight: bold; + +@alert-success-bg: @state-success-bg; +@alert-success-text: @state-success-text; +@alert-success-border: @state-success-border; + +@alert-info-bg: @state-info-bg; +@alert-info-text: @state-info-text; +@alert-info-border: @state-info-border; + +@alert-warning-bg: @state-warning-bg; +@alert-warning-text: @state-warning-text; +@alert-warning-border: @state-warning-border; + +@alert-danger-bg: @state-danger-bg; +@alert-danger-text: @state-danger-text; +@alert-danger-border: @state-danger-border; + + +//== Progress bars +// +//## + +//** Background color of the whole progress component +@progress-bg: #f5f5f5; +//** Progress bar text color +@progress-bar-color: #fff; + +//** Default progress bar color +@progress-bar-bg: @brand-primary; +//** Success progress bar color +@progress-bar-success-bg: @brand-success; +//** Warning progress bar color +@progress-bar-warning-bg: @brand-warning; +//** Danger progress bar color +@progress-bar-danger-bg: @brand-danger; +//** Info progress bar color +@progress-bar-info-bg: @brand-info; + + +//== List group +// +//## + +//** Background color on `.list-group-item` +@list-group-bg: #fff; +//** `.list-group-item` border color +@list-group-border: #ddd; +//** List group border radius +@list-group-border-radius: @border-radius-base; + +//** Background color of single list elements on hover +@list-group-hover-bg: #f5f5f5; +//** Text color of active list elements +@list-group-active-color: @component-active-color; +//** Background color of active list elements +@list-group-active-bg: @component-active-bg; +//** Border color of active list elements +@list-group-active-border: @list-group-active-bg; +@list-group-active-text-color: lighten(@list-group-active-bg, 40%); + +@list-group-link-color: #555; +@list-group-link-heading-color: #333; + + +//== Panels +// +//## + +@panel-bg: #fff; +@panel-body-padding: 15px; +@panel-border-radius: @border-radius-base; + +//** Border color for elements within panels +@panel-inner-border: #ddd; +@panel-footer-bg: #f5f5f5; + +@panel-default-text: @gray-dark; +@panel-default-border: #ddd; +@panel-default-heading-bg: #f5f5f5; + +@panel-primary-text: #fff; +@panel-primary-border: @brand-primary; +@panel-primary-heading-bg: @brand-primary; + +@panel-success-text: @state-success-text; +@panel-success-border: @state-success-border; +@panel-success-heading-bg: @state-success-bg; + +@panel-info-text: @state-info-text; +@panel-info-border: @state-info-border; +@panel-info-heading-bg: @state-info-bg; + +@panel-warning-text: @state-warning-text; +@panel-warning-border: @state-warning-border; +@panel-warning-heading-bg: @state-warning-bg; + +@panel-danger-text: @state-danger-text; +@panel-danger-border: @state-danger-border; +@panel-danger-heading-bg: @state-danger-bg; + + +//== Thumbnails +// +//## + +//** Padding around the thumbnail image +@thumbnail-padding: 4px; +//** Thumbnail background color +@thumbnail-bg: @body-bg; +//** Thumbnail border color +@thumbnail-border: #ddd; +//** Thumbnail border radius +@thumbnail-border-radius: @border-radius-base; + +//** Custom text color for thumbnail captions +@thumbnail-caption-color: @text-color; +//** Padding around the thumbnail caption +@thumbnail-caption-padding: 9px; + + +//== Wells +// +//## + +@well-bg: #f5f5f5; +@well-border: darken(@well-bg, 7%); + + +//== Badges +// +//## + +@badge-color: #fff; +//** Linked badge text color on hover +@badge-link-hover-color: #fff; +@badge-bg: @gray-light; + +//** Badge text color in active nav link +@badge-active-color: @link-color; +//** Badge background color in active nav link +@badge-active-bg: #fff; + +@badge-font-weight: bold; +@badge-line-height: 1; +@badge-border-radius: 10px; + + +//== Breadcrumbs +// +//## + +@breadcrumb-padding-vertical: 8px; +@breadcrumb-padding-horizontal: 15px; +//** Breadcrumb background color +@breadcrumb-bg: #f5f5f5; +//** Breadcrumb text color +@breadcrumb-color: #ccc; +//** Text color of current page in the breadcrumb +@breadcrumb-active-color: @gray-light; +//** Textual separator for between breadcrumb elements +@breadcrumb-separator: "/"; + + +//== Carousel +// +//## + +@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6); + +@carousel-control-color: #fff; +@carousel-control-width: 15%; +@carousel-control-opacity: .5; +@carousel-control-font-size: 20px; + +@carousel-indicator-active-bg: #fff; +@carousel-indicator-border-color: #fff; + +@carousel-caption-color: #fff; + + +//== Close +// +//## + +@close-font-weight: bold; +@close-color: #000; +@close-text-shadow: 0 1px 0 #fff; + + +//== Code +// +//## + +@code-color: #c7254e; +@code-bg: #f9f2f4; + +@kbd-color: #fff; +@kbd-bg: #333; + +@pre-bg: #f5f5f5; +@pre-color: @gray-dark; +@pre-border-color: #ccc; +@pre-scrollable-max-height: 340px; + + +//== Type +// +//## + +//** Text muted color +@text-muted: @gray-light; +//** Abbreviations and acronyms border color +@abbr-border-color: @gray-light; +//** Headings small color +@headings-small-color: @gray-light; +//** Blockquote small color +@blockquote-small-color: @gray-light; +//** Blockquote border color +@blockquote-border-color: @gray-lighter; +//** Page header border color +@page-header-border-color: @gray-lighter; + + +//== Miscellaneous +// +//## + +//** Horizontal line color. +@hr-border: @gray-lighter; + +//** Horizontal offset for forms and lists. +@component-offset-horizontal: 180px; + + +//== Container sizes +// +//## Define the maximum width of `.container` for different screen sizes. + +// Small screen / tablet +@container-tablet: ((720px + @grid-gutter-width)); +//** For `@screen-sm-min` and up. +@container-sm: @container-tablet; + +// Medium screen / desktop +@container-desktop: ((940px + @grid-gutter-width)); +//** For `@screen-md-min` and up. +@container-md: @container-desktop; + +// Large screen / wide desktop +@container-large-desktop: ((1140px + @grid-gutter-width)); +//** For `@screen-lg-min` and up. +@container-lg: @container-large-desktop; diff --git a/dist/bower_components/bootstrap/less/wells.less b/dist/bower_components/bootstrap/less/wells.less new file mode 100644 index 000000000..15d072b0c --- /dev/null +++ b/dist/bower_components/bootstrap/less/wells.less @@ -0,0 +1,29 @@ +// +// Wells +// -------------------------------------------------- + + +// Base class +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: @well-bg; + border: 1px solid @well-border; + border-radius: @border-radius-base; + .box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); + blockquote { + border-color: #ddd; + border-color: rgba(0,0,0,.15); + } +} + +// Sizes +.well-lg { + padding: 24px; + border-radius: @border-radius-large; +} +.well-sm { + padding: 9px; + border-radius: @border-radius-small; +} diff --git a/dist/bower_components/bootstrap/package.json b/dist/bower_components/bootstrap/package.json new file mode 100644 index 000000000..6b38c31ab --- /dev/null +++ b/dist/bower_components/bootstrap/package.json @@ -0,0 +1,71 @@ +{ + "name": "bootstrap", + "description": "Sleek, intuitive, and powerful front-end framework for faster and easier web development.", + "version": "3.1.0", + "keywords": [ + "bootstrap", + "css" + ], + "homepage": "http://getbootstrap.com", + "author": "Twitter, Inc.", + "scripts": { + "test": "grunt test" + }, + "repository": { + "type": "git", + "url": "https://github.com/twbs/bootstrap.git" + }, + "bugs": { + "url": "https://github.com/twbs/bootstrap/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/twbs/bootstrap/blob/master/LICENSE" + } + ], + "devDependencies": { + "browserstack-runner": "~0.0.15", + "btoa": "~1.1.1", + "canonical-json": "~0.0.3", + "grunt": "~0.4.2", + "grunt-banner": "~0.2.0", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-concat": "~0.3.0", + "grunt-contrib-connect": "~0.6.0", + "grunt-contrib-copy": "~0.5.0", + "grunt-contrib-csslint": "~0.2.0", + "grunt-contrib-cssmin": "~0.7.0", + "grunt-contrib-jade": "~0.9.1", + "grunt-contrib-jshint": "~0.8.0", + "grunt-contrib-less": "~0.9.0", + "grunt-contrib-qunit": "~0.4.0", + "grunt-contrib-uglify": "~0.3.0", + "grunt-contrib-watch": "~0.5.3", + "grunt-csscomb": "~2.0.1", + "grunt-exec": "0.4.3", + "grunt-html-validation": "~0.1.13", + "grunt-jekyll": "~0.4.1", + "grunt-jscs-checker": "~0.3.0", + "grunt-saucelabs": "~4.1.2", + "grunt-sed": "~0.1.1", + "load-grunt-tasks": "~0.3.0", + "markdown": "~0.5.0" + }, + "jspm": { + "main": "js/bootstrap", + "directories": { + "example": "examples", + "lib": "dist" + }, + "shim": { + "js/bootstrap": { + "imports": "jquery", + "exports": "$" + } + }, + "buildConfig": { + "uglify": true + } + } +} diff --git a/dist/bower_components/bootstrap/test-infra/README.md b/dist/bower_components/bootstrap/test-infra/README.md new file mode 100644 index 000000000..2ee7ed9ab --- /dev/null +++ b/dist/bower_components/bootstrap/test-infra/README.md @@ -0,0 +1,100 @@ +## What does `s3_cache.py` do? + +### In general +`s3_cache.py` maintains a cache, stored in an Amazon S3 (Simple Storage Service) bucket, of a given directory whose contents are considered non-critical and are completely & solely determined by (and should be able to be regenerated from) a single given file. + +The SHA-256 hash of the single file is used as the key for the cache. The directory is stored as a gzipped tarball. + +All the tarballs are stored in S3's Reduced Redundancy Storage (RRS) storage class, since this is cheaper and the data is non-critical. + +`s3_cache.py` itself never deletes cache entries; deletion should either be done manually or using automatic S3 lifecycle rules on the bucket. + +Similar to git, `s3_cache.py` makes the assumption that [SHA-256 will effectively never have a collision](http://stackoverflow.com/questions/4014090/is-it-safe-to-ignore-the-possibility-of-sha-collisions-in-practice). + + +### For Bootstrap specifically +`s3_cache.py` is used to cache the npm packages that our Grunt tasks depend on and the RubyGems that Jekyll depends on. (Jekyll is needed to compile our docs to HTML so that we can run them thru an HTML5 validator.) + +For npm, the `node_modules` directory is cached based on our `npm-shrinkwrap.canonical.json` file. + +For RubyGems, the `gemdir` of the current RVM-selected Ruby is cached based on the `pseudo_Gemfile.lock` file generated by our Travis build script. +`pseudo_Gemfile.lock` contains the versions of Ruby and Jekyll that we're using (read our `.travis.yml` for details). + + +## Why is `s3_cache.py` necessary? +`s3_cache.py` is used to speed up Bootstrap's Travis builds. Installing npm packages and RubyGems used to take up a significant fraction of our total build times. Also, at the time that `s3_cache.py` was written, npm was occasionally unreliable. + +Travis does offer built-in caching on their paid plans, but this do-it-ourselves S3 solution is significantly cheaper since we only need caching and not Travis' other paid features. + + +## Setup + +### Overview +1. Create an Amazon Web Services (AWS) account. +2. Create an Identity & Access Management (IAM) user, and note their credentials. +3. Create an S3 bucket. +4. Set permissions on the bucket to grant the user read+write access. +5. Set the user credentials as secure Travis environment variables. + +### In detail +1. Create an AWS account. +2. Login to the [AWS Management Console](https://console.aws.amazon.com). +3. Go to the IAM Management Console. +4. Create a new user (named e.g. `travis-ci`) and generate an access key for them. Note both the Access Key ID and the Secret Access Key. +5. Note the user's ARN (Amazon Resource Name), which can be found in the "Summary" tab of the user browser. This will be of the form: `arn:aws:iam::XXXXXXXXXXXXXX:user/the-username-goes-here` +6. Note the user's access key, which can be found in the "Security Credentials" tab of the user browser. +7. Go to the S3 Management Console. +8. Create a new bucket. For a non-publicly-accessible bucket (like Bootstrap uses), it's recommended that the bucket name be random to increase security. On most *nix machines, you can easily generate a random UUID to use as the bucket name using Python: + + ```bash + python -c "import uuid; print(uuid.uuid4())" + ``` + +9. Determine and note what your bucket's ARN is. The ARN for an S3 bucket is of the form: `arn:aws:s3:::the-bucket-name-goes-here` +10. In the bucket's Properties pane, in the "Permissions" section, click the "Edit bucket policy" button. +11. Input and submit an IAM Policy that grants the user at least read+write rights to the bucket. AWS has a policy generator and some examples to help with crafting the policy. Here's the policy that Bootstrap uses, with the sensitive bits censored: + + ```json + { + "Version": "2012-10-17", + "Id": "PolicyTravisReadWriteNoAdmin", + "Statement": [ + { + "Sid": "StmtXXXXXXXXXXXXXX", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::XXXXXXXXXXXXXX:user/travis-ci" + }, + "Action": [ + "s3:AbortMultipartUpload", + "s3:GetObjectVersion", + "s3:ListBucket", + "s3:DeleteObject", + "s3:DeleteObjectVersion", + "s3:GetObject", + "s3:PutObject" + ], + "Resource": [ + "arn:aws:s3:::XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", + "arn:aws:s3:::XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/*" + ] + } + ] + } + ``` + +12. If you want deletion from the cache to be done automatically based on age (like Bootstrap does): In the bucket's Properties pane, in the "Lifecycle" section, add a rule to expire/delete files based on creation date. +13. Install the [`travis` RubyGem](https://github.com/travis-ci/travis): `gem install travis` +14. Encrypt the environment variables: + + ```bash + travis encrypt --repo twbs/bootstrap "AWS_ACCESS_KEY_ID=XXX" + travis encrypt --repo twbs/bootstrap "AWS_SECRET_ACCESS_KEY=XXX" + travis encrypt --repo twbs/bootstrap "TWBS_S3_BUCKET=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" + ``` + +14. Add the resulting secure environment variables to `.travis.yml`. + + +## Usage +Read `s3_cache.py`'s source code and Bootstrap's `.travis.yml` for how to invoke and make use of `s3_cache.py`. diff --git a/dist/bower_components/bootstrap/test-infra/npm-shrinkwrap.canonical.json b/dist/bower_components/bootstrap/test-infra/npm-shrinkwrap.canonical.json new file mode 100644 index 000000000..41b2e201a --- /dev/null +++ b/dist/bower_components/bootstrap/test-infra/npm-shrinkwrap.canonical.json @@ -0,0 +1 @@ +{"dependencies":{"browserstack-runner":{"dependencies":{"browserstack":{"from":"browserstack@1.0.1","resolved":"https://registry.npmjs.org/browserstack/-/browserstack-1.0.1.tgz","version":"1.0.1"}},"from":"browserstack-runner@~0.0.15","resolved":"https://registry.npmjs.org/browserstack-runner/-/browserstack-runner-0.0.15.tgz","version":"0.0.15"},"btoa":{"from":"btoa@~1.1.1","version":"1.1.1"},"canonical-json":{"from":"canonical-json@~0.0.3","resolved":"https://registry.npmjs.org/canonical-json/-/canonical-json-0.0.3.tgz","version":"0.0.3"},"grunt":{"dependencies":{"async":{"from":"async@~0.1.22","version":"0.1.22"},"coffee-script":{"from":"coffee-script@~1.3.3","version":"1.3.3"},"colors":{"from":"colors@~0.6.0","version":"0.6.2"},"dateformat":{"from":"dateformat@1.0.2-1.2.3","resolved":"https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz","version":"1.0.2-1.2.3"},"eventemitter2":{"from":"eventemitter2@~0.4.9","version":"0.4.13"},"exit":{"from":"exit@~0.1.1","version":"0.1.2"},"findup-sync":{"dependencies":{"lodash":{"from":"lodash@~1.0.1","version":"1.0.1"}},"from":"findup-sync@~0.1.2","version":"0.1.2"},"getobject":{"from":"getobject@~0.1.0","version":"0.1.0"},"glob":{"dependencies":{"graceful-fs":{"from":"graceful-fs@~1.2.0","version":"1.2.3"},"inherits":{"from":"inherits@1","version":"1.0.0"}},"from":"glob@~3.1.21","version":"3.1.21"},"hooker":{"from":"hooker@~0.2.3","resolved":"https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz","version":"0.2.3"},"iconv-lite":{"from":"iconv-lite@~0.2.11","version":"0.2.11"},"js-yaml":{"dependencies":{"argparse":{"dependencies":{"underscore":{"from":"underscore@~1.4.3","version":"1.4.4"},"underscore.string":{"from":"underscore.string@~2.3.1","version":"2.3.3"}},"from":"argparse@~ 0.1.11","version":"0.1.15"},"esprima":{"from":"esprima@~ 1.0.2","version":"1.0.4"}},"from":"js-yaml@~2.0.5","version":"2.0.5"},"lodash":{"from":"lodash@~0.9.2","version":"0.9.2"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.11","version":"0.2.14"},"nopt":{"dependencies":{"abbrev":{"from":"abbrev@1","version":"1.0.4"}},"from":"nopt@~1.0.10","version":"1.0.10"},"rimraf":{"dependencies":{"graceful-fs":{"from":"graceful-fs@~1.1","version":"1.1.14"}},"from":"rimraf@~2.0.3","version":"2.0.3"},"underscore.string":{"from":"underscore.string@~2.2.1","version":"2.2.1"},"which":{"from":"which@~1.0.5","version":"1.0.5"}},"from":"grunt@~0.4.2","version":"0.4.2"},"grunt-banner":{"from":"grunt-banner@~0.2.0","version":"0.2.0"},"grunt-contrib-clean":{"dependencies":{"rimraf":{"from":"rimraf@~2.2.1","resolved":"https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz","version":"2.2.6"}},"from":"grunt-contrib-clean@~0.5.0","version":"0.5.0"},"grunt-contrib-concat":{"from":"grunt-contrib-concat@~0.3.0","version":"0.3.0"},"grunt-contrib-connect":{"dependencies":{"connect":{"dependencies":{"batch":{"from":"batch@0.5.0","resolved":"https://registry.npmjs.org/batch/-/batch-0.5.0.tgz","version":"0.5.0"},"buffer-crc32":{"from":"buffer-crc32@0.2.1","resolved":"https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz","version":"0.2.1"},"bytes":{"from":"bytes@0.2.1","resolved":"https://registry.npmjs.org/bytes/-/bytes-0.2.1.tgz","version":"0.2.1"},"cookie":{"from":"cookie@0.1.0","resolved":"https://registry.npmjs.org/cookie/-/cookie-0.1.0.tgz","version":"0.1.0"},"cookie-signature":{"from":"cookie-signature@1.0.1","resolved":"https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.1.tgz","version":"1.0.1"},"debug":{"from":"debug@~0.7.2","version":"0.7.4"},"fresh":{"from":"fresh@0.2.0","resolved":"https://registry.npmjs.org/fresh/-/fresh-0.2.0.tgz","version":"0.2.0"},"methods":{"from":"methods@0.1.0","resolved":"https://registry.npmjs.org/methods/-/methods-0.1.0.tgz","version":"0.1.0"},"multiparty":{"dependencies":{"readable-stream":{"dependencies":{"core-util-is":{"from":"core-util-is@~1.0.0","version":"1.0.1"},"debuglog":{"from":"debuglog@0.0.2","resolved":"https://registry.npmjs.org/debuglog/-/debuglog-0.0.2.tgz","version":"0.0.2"}},"from":"readable-stream@~1.1.9","version":"1.1.10"},"stream-counter":{"from":"stream-counter@~0.2.0","version":"0.2.0"}},"from":"multiparty@2.2.0","resolved":"https://registry.npmjs.org/multiparty/-/multiparty-2.2.0.tgz","version":"2.2.0"},"negotiator":{"from":"negotiator@0.3.0","resolved":"https://registry.npmjs.org/negotiator/-/negotiator-0.3.0.tgz","version":"0.3.0"},"pause":{"from":"pause@0.0.1","resolved":"https://registry.npmjs.org/pause/-/pause-0.0.1.tgz","version":"0.0.1"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"raw-body":{"from":"raw-body@1.1.2","resolved":"https://registry.npmjs.org/raw-body/-/raw-body-1.1.2.tgz","version":"1.1.2"},"send":{"dependencies":{"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"range-parser":{"from":"range-parser@0.0.4","resolved":"https://registry.npmjs.org/range-parser/-/range-parser-0.0.4.tgz","version":"0.0.4"}},"from":"send@0.1.4","resolved":"https://registry.npmjs.org/send/-/send-0.1.4.tgz","version":"0.1.4"},"uid2":{"from":"uid2@0.0.3","resolved":"https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz","version":"0.0.3"}},"from":"connect@~2.12.0","version":"2.12.0"},"connect-livereload":{"from":"connect-livereload@~0.3.0","version":"0.3.2"},"open":{"from":"open@0.0.4","resolved":"https://registry.npmjs.org/open/-/open-0.0.4.tgz","version":"0.0.4"}},"from":"grunt-contrib-connect@~0.6.0","version":"0.6.0"},"grunt-contrib-copy":{"from":"grunt-contrib-copy@~0.5.0","version":"0.5.0"},"grunt-contrib-csslint":{"dependencies":{"csslint":{"dependencies":{"parserlib":{"from":"parserlib@~0.2.2","resolved":"https://registry.npmjs.org/parserlib/-/parserlib-0.2.4.tgz","version":"0.2.4"}},"from":"csslint@~0.10.0","version":"0.10.0"}},"from":"grunt-contrib-csslint@~0.2.0","version":"0.2.0"},"grunt-contrib-cssmin":{"dependencies":{"clean-css":{"dependencies":{"commander":{"from":"commander@2.0.x","version":"2.0.0"}},"from":"clean-css@~2.0.0","version":"2.0.6"},"grunt-lib-contrib":{"dependencies":{"zlib-browserify":{"from":"zlib-browserify@0.0.1","resolved":"https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz","version":"0.0.1"}},"from":"grunt-lib-contrib@~0.6.0","version":"0.6.1"}},"from":"grunt-contrib-cssmin@~0.7.0","version":"0.7.0"},"grunt-contrib-jade":{"dependencies":{"grunt-lib-contrib":{"dependencies":{"zlib-browserify":{"from":"zlib-browserify@0.0.1","resolved":"https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz","version":"0.0.1"}},"from":"grunt-lib-contrib@~0.6.1","version":"0.6.1"},"jade":{"dependencies":{"character-parser":{"from":"character-parser@1.2.0","resolved":"https://registry.npmjs.org/character-parser/-/character-parser-1.2.0.tgz","version":"1.2.0"},"commander":{"from":"commander@2.0.0","resolved":"https://registry.npmjs.org/commander/-/commander-2.0.0.tgz","version":"2.0.0"},"constantinople":{"dependencies":{"uglify-js":{"dependencies":{"async":{"from":"async@~0.2.6","version":"0.2.9"},"optimist":{"dependencies":{"wordwrap":{"from":"wordwrap@~0.0.2","version":"0.0.2"}},"from":"optimist@~0.3.5","version":"0.3.7"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@~0.1.7","version":"0.1.31"},"uglify-to-browserify":{"from":"uglify-to-browserify@~1.0.0","version":"1.0.1"}},"from":"uglify-js@~2.4.0","resolved":"https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.9.tgz","version":"2.4.9"}},"from":"constantinople@~1.0.2","version":"1.0.2"},"mkdirp":{"from":"mkdirp@~0.3.5","resolved":"https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz","version":"0.3.5"},"monocle":{"dependencies":{"readdirp":{"dependencies":{"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@>=0.2.4","version":"0.2.14"}},"from":"readdirp@~0.2.3","version":"0.2.5"}},"from":"monocle@1.1.50","resolved":"https://registry.npmjs.org/monocle/-/monocle-1.1.50.tgz","version":"1.1.50"},"transformers":{"dependencies":{"css":{"dependencies":{"css-parse":{"from":"css-parse@1.0.4","resolved":"https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz","version":"1.0.4"},"css-stringify":{"from":"css-stringify@1.0.5","resolved":"https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz","version":"1.0.5"}},"from":"css@~1.0.8","version":"1.0.8"},"promise":{"dependencies":{"is-promise":{"from":"is-promise@~1","version":"1.0.0"}},"from":"promise@~2.0","version":"2.0.0"},"uglify-js":{"dependencies":{"optimist":{"dependencies":{"wordwrap":{"from":"wordwrap@~0.0.2","version":"0.0.2"}},"from":"optimist@~0.3.5","version":"0.3.7"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@~0.1.7","version":"0.1.31"}},"from":"uglify-js@~2.2.5","version":"2.2.5"}},"from":"transformers@2.1.0","resolved":"https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz","version":"2.1.0"},"with":{"dependencies":{"uglify-js":{"dependencies":{"async":{"from":"async@~0.2.6","version":"0.2.9"},"optimist":{"dependencies":{"wordwrap":{"from":"wordwrap@~0.0.2","version":"0.0.2"}},"from":"optimist@~0.3.5","version":"0.3.7"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@~0.1.7","version":"0.1.31"},"uglify-to-browserify":{"from":"uglify-to-browserify@~1.0.0","version":"1.0.1"}},"from":"uglify-js@2.4.0","resolved":"https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.0.tgz","version":"2.4.0"}},"from":"with@~2.0.0","version":"2.0.0"}},"from":"jade@~1.0.2","version":"1.0.2"},"lodash-node":{"from":"lodash-node@~2.4.1","version":"2.4.1"}},"from":"grunt-contrib-jade@~0.9.1","version":"0.9.1"},"grunt-contrib-jshint":{"dependencies":{"jshint":{"dependencies":{"cli":{"dependencies":{"glob":{"dependencies":{"inherits":{"from":"inherits@2","version":"2.0.1"}},"from":"glob@>= 3.1.4","version":"3.2.8"}},"from":"cli@0.4.x","version":"0.4.5"},"console-browserify":{"from":"console-browserify@0.1.x","version":"0.1.6"},"htmlparser2":{"dependencies":{"domelementtype":{"from":"domelementtype@1","version":"1.1.1"},"domhandler":{"from":"domhandler@2.1","version":"2.1.0"},"domutils":{"from":"domutils@1.1","version":"1.1.6"},"readable-stream":{"from":"readable-stream@1.0","version":"1.0.24"}},"from":"htmlparser2@3.3.x","version":"3.3.0"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@0.x.x","version":"0.2.14"},"shelljs":{"from":"shelljs@0.1.x","version":"0.1.4"},"underscore":{"from":"underscore@1.4.x","version":"1.4.4"}},"from":"jshint@~2.4.0","version":"2.4.1"}},"from":"grunt-contrib-jshint@~0.8.0","version":"0.8.0"},"grunt-contrib-less":{"dependencies":{"chalk":{"dependencies":{"ansi-styles":{"from":"ansi-styles@~1.0.0","version":"1.0.0"},"has-color":{"from":"has-color@~0.1.0","version":"0.1.2"},"strip-ansi":{"from":"strip-ansi@~0.1.0","version":"0.1.1"}},"from":"chalk@~0.4.0","version":"0.4.0"},"grunt-lib-contrib":{"dependencies":{"zlib-browserify":{"from":"zlib-browserify@0.0.1","resolved":"https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz","version":"0.0.1"}},"from":"grunt-lib-contrib@~0.6.1","version":"0.6.1"},"less":{"dependencies":{"clean-css":{"dependencies":{"commander":{"from":"commander@2.0.x","resolved":"https://registry.npmjs.org/commander/-/commander-2.0.0.tgz","version":"2.0.0"}},"from":"clean-css@2.0.x","version":"2.0.6"},"mime":{"from":"mime@1.2.x","version":"1.2.11"},"mkdirp":{"from":"mkdirp@~0.3.5","resolved":"https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz","version":"0.3.5"},"request":{"dependencies":{"aws-sign2":{"from":"aws-sign2@~0.5.0","version":"0.5.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"async":{"from":"async@~0.2.9","version":"0.2.9"},"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@~0.1.0","version":"0.1.2"},"hawk":{"dependencies":{"boom":{"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.9.x","version":"0.9.1"},"sntp":{"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~1.0.0","version":"1.0.0"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.10.0","version":"0.10.0"},"json-stringify-safe":{"from":"json-stringify-safe@~5.0.0","version":"5.0.0"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"tough-cookie":{"dependencies":{"punycode":{"from":"punycode@>=0.2.0","version":"1.2.3"}},"from":"tough-cookie@~0.9.15","version":"0.9.15"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@>=2.12.0","version":"2.31.0"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@0.1.x","version":"0.1.31"}},"from":"less@~1.6.0","resolved":"https://registry.npmjs.org/less/-/less-1.6.1.tgz","version":"1.6.1"}},"from":"grunt-contrib-less@~0.9.0","version":"0.9.0"},"grunt-contrib-qunit":{"dependencies":{"grunt-lib-phantomjs":{"dependencies":{"eventemitter2":{"from":"eventemitter2@~0.4.9","version":"0.4.13"},"phantomjs":{"dependencies":{"adm-zip":{"from":"adm-zip@0.2.1","resolved":"https://registry.npmjs.org/adm-zip/-/adm-zip-0.2.1.tgz","version":"0.2.1"},"kew":{"from":"kew@~0.1.7","version":"0.1.7"},"mkdirp":{"from":"mkdirp@0.3.5","resolved":"https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz","version":"0.3.5"},"ncp":{"from":"ncp@0.4.2","resolved":"https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz","version":"0.4.2"},"npmconf":{"dependencies":{"config-chain":{"dependencies":{"proto-list":{"from":"proto-list@~1.2.1","version":"1.2.2"}},"from":"config-chain@~1.1.1","version":"1.1.8"},"inherits":{"from":"inherits@~1.0.0","version":"1.0.0"},"ini":{"from":"ini@~1.1.0","version":"1.1.0"},"nopt":{"dependencies":{"abbrev":{"from":"abbrev@1","version":"1.0.4"}},"from":"nopt@2","version":"2.1.2"},"once":{"from":"once@~1.1.1","version":"1.1.1"},"osenv":{"from":"osenv@0.0.3","resolved":"https://registry.npmjs.org/osenv/-/osenv-0.0.3.tgz","version":"0.0.3"},"semver":{"from":"semver@~1.1.0","version":"1.1.4"}},"from":"npmconf@0.0.24","resolved":"https://registry.npmjs.org/npmconf/-/npmconf-0.0.24.tgz","version":"0.0.24"},"rimraf":{"from":"rimraf@~2.2.2","version":"2.2.6"},"which":{"from":"which@~1.0.5","version":"1.0.5"}},"from":"phantomjs@~1.9.0-1","resolved":"https://registry.npmjs.org/phantomjs/-/phantomjs-1.9.7-1.tgz","version":"1.9.7-1"},"semver":{"from":"semver@~1.0.14","version":"1.0.14"},"temporary":{"dependencies":{"package":{"from":"package@>= 1.0.0 < 1.2.0","version":"1.0.1"}},"from":"temporary@~0.0.4","version":"0.0.8"}},"from":"grunt-lib-phantomjs@~0.5.0","resolved":"https://registry.npmjs.org/grunt-lib-phantomjs/-/grunt-lib-phantomjs-0.5.0.tgz","version":"0.5.0"}},"from":"grunt-contrib-qunit@~0.4.0","resolved":"https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-0.4.0.tgz","version":"0.4.0"},"grunt-contrib-uglify":{"dependencies":{"chalk":{"dependencies":{"ansi-styles":{"from":"ansi-styles@~1.0.0","version":"1.0.0"},"has-color":{"from":"has-color@~0.1.0","version":"0.1.2"},"strip-ansi":{"from":"strip-ansi@~0.1.0","version":"0.1.1"}},"from":"chalk@~0.4.0","version":"0.4.0"},"grunt-lib-contrib":{"dependencies":{"zlib-browserify":{"from":"zlib-browserify@0.0.1","resolved":"https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz","version":"0.0.1"}},"from":"grunt-lib-contrib@~0.6.1","version":"0.6.1"},"uglify-js":{"dependencies":{"async":{"from":"async@~0.2.6","resolved":"https://registry.npmjs.org/async/-/async-0.2.10.tgz","version":"0.2.10"},"optimist":{"dependencies":{"wordwrap":{"from":"wordwrap@~0.0.2","version":"0.0.2"}},"from":"optimist@~0.3.5","version":"0.3.7"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@~0.1.7","version":"0.1.31"},"uglify-to-browserify":{"from":"uglify-to-browserify@~1.0.0","version":"1.0.1"}},"from":"uglify-js@~2.4.0","resolved":"https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.12.tgz","version":"2.4.12"}},"from":"grunt-contrib-uglify@~0.3.0","resolved":"https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-0.3.2.tgz","version":"0.3.2"},"grunt-contrib-watch":{"dependencies":{"gaze":{"dependencies":{"globule":{"dependencies":{"glob":{"dependencies":{"graceful-fs":{"from":"graceful-fs@~1.2.0","version":"1.2.3"},"inherits":{"from":"inherits@1","version":"1.0.0"}},"from":"glob@~3.1.21","version":"3.1.21"},"lodash":{"from":"lodash@~1.0.1","version":"1.0.1"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.11","version":"0.2.14"}},"from":"globule@~0.1.0","version":"0.1.0"}},"from":"gaze@~0.4.0","version":"0.4.3"},"tiny-lr":{"dependencies":{"debug":{"from":"debug@~0.7.2","version":"0.7.4"},"faye-websocket":{"from":"faye-websocket@~0.4.3","version":"0.4.4"},"noptify":{"dependencies":{"nopt":{"dependencies":{"abbrev":{"from":"abbrev@1","version":"1.0.4"}},"from":"nopt@~2.0.0","version":"2.0.0"}},"from":"noptify@latest","version":"0.0.3"},"qs":{"from":"qs@~0.5.2","version":"0.5.6"}},"from":"tiny-lr@0.0.4","resolved":"https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.0.4.tgz","version":"0.0.4"}},"from":"grunt-contrib-watch@~0.5.3","version":"0.5.3"},"grunt-csscomb":{"dependencies":{"csscomb":{"dependencies":{"commander":{"from":"commander@2.0.0","resolved":"https://registry.npmjs.org/commander/-/commander-2.0.0.tgz","version":"2.0.0"},"gonzales-pe":{"from":"gonzales-pe@2.0.x","resolved":"https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-2.0.2.tgz","version":"2.0.2"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@0.2.12","resolved":"https://registry.npmjs.org/minimatch/-/minimatch-0.2.12.tgz","version":"0.2.12"},"vow":{"from":"vow@0.3.11","resolved":"https://registry.npmjs.org/vow/-/vow-0.3.11.tgz","version":"0.3.11"},"vow-fs":{"dependencies":{"node-uuid":{"from":"node-uuid@1.4.0","resolved":"https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.0.tgz","version":"1.4.0"},"vow-queue":{"from":"vow-queue@0.0.2","resolved":"https://registry.npmjs.org/vow-queue/-/vow-queue-0.0.2.tgz","version":"0.0.2"}},"from":"vow-fs@0.2.3","resolved":"https://registry.npmjs.org/vow-fs/-/vow-fs-0.2.3.tgz","version":"0.2.3"}},"from":"csscomb@~2.0.0","resolved":"https://registry.npmjs.org/csscomb/-/csscomb-2.0.4.tgz","version":"2.0.4"}},"from":"grunt-csscomb@~2.0.1","version":"2.0.1"},"grunt-exec":{"from":"grunt-exec@0.4.3","resolved":"https://registry.npmjs.org/grunt-exec/-/grunt-exec-0.4.3.tgz","version":"0.4.3"},"grunt-html-validation":{"dependencies":{"colors":{"from":"colors@~0.6.0","version":"0.6.2"},"request":{"dependencies":{"aws-sign":{"from":"aws-sign@~0.3.0","version":"0.3.0"},"cookie-jar":{"from":"cookie-jar@~0.3.0","version":"0.3.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"async":{"from":"async@~0.2.9","version":"0.2.9"},"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@~0.1.0","version":"0.1.2"},"hawk":{"dependencies":{"boom":{"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.9.x","version":"0.9.1"},"sntp":{"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~1.0.0","version":"1.0.0"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.10.0","version":"0.10.0"},"json-stringify-safe":{"from":"json-stringify-safe@~5.0.0","version":"5.0.0"},"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","version":"0.6.6"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@~2.27.0","version":"2.27.0"},"w3cjs":{"dependencies":{"commander":{"from":"commander@2.0.x","version":"2.0.0"},"superagent":{"dependencies":{"cookiejar":{"from":"cookiejar@1.3.0","resolved":"https://registry.npmjs.org/cookiejar/-/cookiejar-1.3.0.tgz","version":"1.3.0"},"debug":{"from":"debug@~0.7.2","version":"0.7.4"},"emitter-component":{"from":"emitter-component@1.0.0","resolved":"https://registry.npmjs.org/emitter-component/-/emitter-component-1.0.0.tgz","version":"1.0.0"},"formidable":{"from":"formidable@1.0.14","resolved":"https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz","version":"1.0.14"},"methods":{"from":"methods@0.0.1","resolved":"https://registry.npmjs.org/methods/-/methods-0.0.1.tgz","version":"0.0.1"},"mime":{"from":"mime@1.2.5","resolved":"https://registry.npmjs.org/mime/-/mime-1.2.5.tgz","version":"1.2.5"},"qs":{"from":"qs@0.6.5","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.5.tgz","version":"0.6.5"},"reduce-component":{"from":"reduce-component@1.0.1","resolved":"https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz","version":"1.0.1"}},"from":"superagent@~0.15.7","version":"0.15.7"},"superagent-proxy":{"dependencies":{"proxy-agent":{"dependencies":{"http-proxy-agent":{"dependencies":{"agent-base":{"from":"agent-base@~1.0.1","version":"1.0.1"},"debug":{"from":"debug@~0.7.0","version":"0.7.4"},"extend":{"from":"extend@~1.2.0","version":"1.2.1"}},"from":"http-proxy-agent@0","resolved":"https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-0.2.4.tgz","version":"0.2.4"},"https-proxy-agent":{"dependencies":{"agent-base":{"from":"agent-base@~1.0.1","version":"1.0.1"},"debug":{"from":"debug@~0.7.0","version":"0.7.4"},"extend":{"from":"extend@~1.2.0","version":"1.2.1"}},"from":"https-proxy-agent@0","resolved":"https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-0.3.3.tgz","version":"0.3.3"},"lru-cache":{"from":"lru-cache@~2.3.1","version":"2.3.1"},"socks-proxy-agent":{"dependencies":{"agent-base":{"from":"agent-base@~1.0.1","version":"1.0.1"},"extend":{"from":"extend@~1.2.0","version":"1.2.1"},"rainbowsocks":{"dependencies":{"debug":{"from":"debug@~0.7.2","version":"0.7.4"}},"from":"rainbowsocks@~0.1.0","version":"0.1.1"}},"from":"socks-proxy-agent@0","version":"0.1.0"}},"from":"proxy-agent@~0.0.2","version":"0.0.2"}},"from":"superagent-proxy@~0.2.0","version":"0.2.0"}},"from":"w3cjs@~0.1.22","version":"0.1.22"}},"from":"grunt-html-validation@~0.1.13","version":"0.1.13"},"grunt-jekyll":{"dependencies":{"tmp":{"from":"tmp@0.0.21","resolved":"https://registry.npmjs.org/tmp/-/tmp-0.0.21.tgz","version":"0.0.21"}},"from":"grunt-jekyll@~0.4.1","version":"0.4.1"},"grunt-jscs-checker":{"dependencies":{"hooker":{"from":"hooker@~0.2.3","resolved":"https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz","version":"0.2.3"},"jscs":{"dependencies":{"colors":{"from":"colors@0.6.0-1","resolved":"https://registry.npmjs.org/colors/-/colors-0.6.0-1.tgz","version":"0.6.0-1"},"commander":{"dependencies":{"keypress":{"from":"keypress@0.1.x","version":"0.1.0"}},"from":"commander@1.2.0","resolved":"https://registry.npmjs.org/commander/-/commander-1.2.0.tgz","version":"1.2.0"},"esprima":{"from":"esprima@1.0.3","resolved":"https://registry.npmjs.org/esprima/-/esprima-1.0.3.tgz","version":"1.0.3"},"glob":{"dependencies":{"inherits":{"from":"inherits@2","version":"2.0.1"}},"from":"glob@3.2.7","resolved":"https://registry.npmjs.org/glob/-/glob-3.2.7.tgz","version":"3.2.7"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@0.2.12","resolved":"https://registry.npmjs.org/minimatch/-/minimatch-0.2.12.tgz","version":"0.2.12"},"vow":{"from":"vow@0.3.9","resolved":"https://registry.npmjs.org/vow/-/vow-0.3.9.tgz","version":"0.3.9"},"vow-fs":{"dependencies":{"node-uuid":{"from":"node-uuid@1.4.0","resolved":"https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.0.tgz","version":"1.4.0"},"vow-queue":{"from":"vow-queue@0.0.2","resolved":"https://registry.npmjs.org/vow-queue/-/vow-queue-0.0.2.tgz","version":"0.0.2"}},"from":"vow-fs@0.2.3","resolved":"https://registry.npmjs.org/vow-fs/-/vow-fs-0.2.3.tgz","version":"0.2.3"},"xmlbuilder":{"dependencies":{"underscore":{"from":"underscore@>=1.5.x","version":"1.5.2"}},"from":"xmlbuilder@1.1.2","resolved":"https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-1.1.2.tgz","version":"1.1.2"}},"from":"jscs@~1.2.0","resolved":"https://registry.npmjs.org/jscs/-/jscs-1.2.3.tgz","version":"1.2.3"},"lodash.assign":{"dependencies":{"lodash._basecreatecallback":{"dependencies":{"lodash._setbinddata":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"},"lodash.noop":{"from":"lodash.noop@~2.4.1","version":"2.4.1"}},"from":"lodash._setbinddata@~2.4.1","version":"2.4.1"},"lodash.bind":{"dependencies":{"lodash._createwrapper":{"dependencies":{"lodash._basebind":{"dependencies":{"lodash._basecreate":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"},"lodash.noop":{"from":"lodash.noop@~2.4.1","version":"2.4.1"}},"from":"lodash._basecreate@~2.4.1","version":"2.4.1"},"lodash.isobject":{"from":"lodash.isobject@~2.4.1","version":"2.4.1"}},"from":"lodash._basebind@~2.4.1","version":"2.4.1"},"lodash._basecreatewrapper":{"dependencies":{"lodash._basecreate":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"},"lodash.noop":{"from":"lodash.noop@~2.4.1","version":"2.4.1"}},"from":"lodash._basecreate@~2.4.1","version":"2.4.1"},"lodash.isobject":{"from":"lodash.isobject@~2.4.1","version":"2.4.1"}},"from":"lodash._basecreatewrapper@~2.4.1","version":"2.4.1"},"lodash.isfunction":{"from":"lodash.isfunction@~2.4.1","version":"2.4.1"}},"from":"lodash._createwrapper@~2.4.1","version":"2.4.1"},"lodash._slice":{"from":"lodash._slice@~2.4.1","version":"2.4.1"}},"from":"lodash.bind@~2.4.1","version":"2.4.1"},"lodash.identity":{"from":"lodash.identity@~2.4.1","version":"2.4.1"},"lodash.support":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"}},"from":"lodash.support@~2.4.1","version":"2.4.1"}},"from":"lodash._basecreatecallback@~2.4.1","version":"2.4.1"},"lodash._objecttypes":{"from":"lodash._objecttypes@~2.4.1","version":"2.4.1"},"lodash.keys":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"},"lodash._shimkeys":{"from":"lodash._shimkeys@~2.4.1","version":"2.4.1"},"lodash.isobject":{"from":"lodash.isobject@~2.4.1","version":"2.4.1"}},"from":"lodash.keys@~2.4.1","version":"2.4.1"}},"from":"lodash.assign@2.4.1","resolved":"https://registry.npmjs.org/lodash.assign/-/lodash.assign-2.4.1.tgz","version":"2.4.1"},"vow":{"from":"vow@0.4.0","resolved":"https://registry.npmjs.org/vow/-/vow-0.4.0.tgz","version":"0.4.0"}},"from":"grunt-jscs-checker@~0.3.0","resolved":"https://registry.npmjs.org/grunt-jscs-checker/-/grunt-jscs-checker-0.3.2.tgz","version":"0.3.2"},"grunt-saucelabs":{"dependencies":{"colors":{"from":"colors@~0.6.0","version":"0.6.2"},"request":{"dependencies":{"aws-sign":{"from":"aws-sign@~0.3.0","version":"0.3.0"},"cookie-jar":{"from":"cookie-jar@~0.3.0","version":"0.3.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"async":{"from":"async@~0.2.9","version":"0.2.9"},"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@~0.1.0","version":"0.1.2"},"hawk":{"dependencies":{"boom":{"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.9.x","version":"0.9.1"},"sntp":{"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~1.0.0","version":"1.0.0"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.10.0","version":"0.10.0"},"json-stringify-safe":{"from":"json-stringify-safe@~5.0.0","version":"5.0.0"},"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@~2.27.0","version":"2.27.0"},"sauce-tunnel":{"dependencies":{"request":{"dependencies":{"aws-sign":{"from":"aws-sign@~0.3.0","version":"0.3.0"},"cookie-jar":{"from":"cookie-jar@~0.3.0","version":"0.3.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"async":{"from":"async@~0.2.7","version":"0.2.9"},"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@0.0.8","resolved":"https://registry.npmjs.org/form-data/-/form-data-0.0.8.tgz","version":"0.0.8"},"hawk":{"dependencies":{"boom":{"dependencies":{"hoek":{"from":"hoek@0.9.x","version":"0.9.1"}},"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.8.x","version":"0.8.5"},"sntp":{"dependencies":{"hoek":{"from":"hoek@0.9.x","version":"0.9.1"}},"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~0.13.0","version":"0.13.1"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.9.11","version":"0.9.11"},"json-stringify-safe":{"from":"json-stringify-safe@~4.0.0","version":"4.0.0"},"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@~2.21.0","version":"2.21.0"}},"from":"sauce-tunnel@~1.0.0","version":"1.0.2"},"saucelabs":{"from":"saucelabs@~0.1.0","version":"0.1.1"},"wd":{"dependencies":{"archiver":{"dependencies":{"iconv-lite":{"from":"iconv-lite@~0.2.11","version":"0.2.11"},"readable-stream":{"from":"readable-stream@~1.0.2","version":"1.0.24"}},"from":"archiver@~0.4.6","version":"0.4.10"},"async":{"from":"async@0.2.x","version":"0.2.9"},"lodash":{"from":"lodash@~1.3.1","version":"1.3.1"},"q":{"from":"q@0.9.x","version":"0.9.7"},"request":{"dependencies":{"aws-sign":{"from":"aws-sign@~0.3.0","version":"0.3.0"},"cookie-jar":{"from":"cookie-jar@~0.3.0","version":"0.3.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@0.0.8","resolved":"https://registry.npmjs.org/form-data/-/form-data-0.0.8.tgz","version":"0.0.8"},"hawk":{"dependencies":{"boom":{"dependencies":{"hoek":{"from":"hoek@0.9.x","version":"0.9.1"}},"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.8.x","version":"0.8.5"},"sntp":{"dependencies":{"hoek":{"from":"hoek@0.9.x","version":"0.9.1"}},"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~0.13.0","version":"0.13.1"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.9.11","version":"0.9.11"},"json-stringify-safe":{"from":"json-stringify-safe@~4.0.0","version":"4.0.0"},"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@~2.21.0","version":"2.21.0"},"vargs":{"from":"vargs@~0.1.0","version":"0.1.0"}},"from":"wd@~0.1.0","version":"0.1.5"}},"from":"grunt-saucelabs@~4.1.2","version":"4.1.2"},"grunt-sed":{"dependencies":{"replace":{"dependencies":{"colors":{"from":"colors@0.5.x","version":"0.5.1"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.9","version":"0.2.14"},"nomnom":{"dependencies":{"underscore":{"from":"underscore@~1.4.4","version":"1.4.4"}},"from":"nomnom@1.6.x","version":"1.6.2"}},"from":"replace@~0.2.4","version":"0.2.7"}},"from":"grunt-sed@~0.1.1","version":"0.1.1"},"load-grunt-tasks":{"dependencies":{"findup-sync":{"dependencies":{"glob":{"dependencies":{"graceful-fs":{"from":"graceful-fs@~1.2.0","version":"1.2.3"},"inherits":{"from":"inherits@1","version":"1.0.0"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.11","version":"0.2.14"}},"from":"glob@~3.1.21","version":"3.1.21"},"lodash":{"from":"lodash@~1.0.1","version":"1.0.1"}},"from":"findup-sync@~0.1.2","version":"0.1.2"},"globule":{"dependencies":{"glob":{"dependencies":{"inherits":{"from":"inherits@2","version":"2.0.1"}},"from":"glob@~3.2.7","version":"3.2.8"},"lodash":{"from":"lodash@~2.4.1","resolved":"https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz","version":"2.4.1"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.11","version":"0.2.14"}},"from":"globule@~0.2.0","resolved":"https://registry.npmjs.org/globule/-/globule-0.2.0.tgz","version":"0.2.0"}},"from":"load-grunt-tasks@~0.3.0","resolved":"https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-0.3.0.tgz","version":"0.3.0"},"markdown":{"dependencies":{"nopt":{"dependencies":{"abbrev":{"from":"abbrev@1","version":"1.0.4"}},"from":"nopt@~2.1.1","version":"2.1.2"}},"from":"markdown@~0.5.0","version":"0.5.0"}},"name":"bootstrap","version":"3.1.0"} \ No newline at end of file diff --git a/dist/bower_components/bootstrap/test-infra/requirements.txt b/dist/bower_components/bootstrap/test-infra/requirements.txt new file mode 100644 index 000000000..95fbf1a3b --- /dev/null +++ b/dist/bower_components/bootstrap/test-infra/requirements.txt @@ -0,0 +1 @@ +boto==2.20.0 diff --git a/dist/bower_components/bootstrap/test-infra/s3_cache.py b/dist/bower_components/bootstrap/test-infra/s3_cache.py new file mode 100644 index 000000000..adc466e00 --- /dev/null +++ b/dist/bower_components/bootstrap/test-infra/s3_cache.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python2.7 +from __future__ import absolute_import, unicode_literals, print_function, division + +from sys import argv +from os import environ, stat, remove as _delete_file +from os.path import isfile, dirname, basename, abspath +from hashlib import sha256 +from subprocess import check_call as run + +from boto.s3.connection import S3Connection +from boto.s3.key import Key +from boto.exception import S3ResponseError + + +NEED_TO_UPLOAD_MARKER = '.need-to-upload' +BYTES_PER_MB = 1024 * 1024 +try: + BUCKET_NAME = environ['TWBS_S3_BUCKET'] +except KeyError: + raise SystemExit("TWBS_S3_BUCKET environment variable not set!") + + +def _sha256_of_file(filename): + hasher = sha256() + with open(filename, 'rb') as input_file: + hasher.update(input_file.read()) + file_hash = hasher.hexdigest() + print('sha256({}) = {}'.format(filename, file_hash)) + return file_hash + + +def _delete_file_quietly(filename): + try: + _delete_file(filename) + except (OSError, IOError): + pass + + +def _tarball_size(directory): + kib = stat(_tarball_filename_for(directory)).st_size // BYTES_PER_MB + return "{} MiB".format(kib) + + +def _tarball_filename_for(directory): + return abspath('./{}.tar.gz'.format(basename(directory))) + + +def _create_tarball(directory): + print("Creating tarball of {}...".format(directory)) + run(['tar', '-czf', _tarball_filename_for(directory), '-C', dirname(directory), basename(directory)]) + + +def _extract_tarball(directory): + print("Extracting tarball of {}...".format(directory)) + run(['tar', '-xzf', _tarball_filename_for(directory), '-C', dirname(directory)]) + + +def download(directory): + _delete_file_quietly(NEED_TO_UPLOAD_MARKER) + try: + print("Downloading {} tarball from S3...".format(friendly_name)) + key.get_contents_to_filename(_tarball_filename_for(directory)) + except S3ResponseError as err: + open(NEED_TO_UPLOAD_MARKER, 'a').close() + print(err) + raise SystemExit("Cached {} download failed!".format(friendly_name)) + print("Downloaded {}.".format(_tarball_size(directory))) + _extract_tarball(directory) + print("{} successfully installed from cache.".format(friendly_name)) + + +def upload(directory): + _create_tarball(directory) + print("Uploading {} tarball to S3... ({})".format(friendly_name, _tarball_size(directory))) + key.set_contents_from_filename(_tarball_filename_for(directory)) + print("{} cache successfully updated.".format(friendly_name)) + _delete_file_quietly(NEED_TO_UPLOAD_MARKER) + + +if __name__ == '__main__': + # Uses environment variables: + # AWS_ACCESS_KEY_ID -- AWS Access Key ID + # AWS_SECRET_ACCESS_KEY -- AWS Secret Access Key + argv.pop(0) + if len(argv) != 4: + raise SystemExit("USAGE: s3_cache.py ") + mode, friendly_name, dependencies_file, directory = argv + + conn = S3Connection() + bucket = conn.lookup(BUCKET_NAME) + if bucket is None: + raise SystemExit("Could not access bucket!") + + dependencies_file_hash = _sha256_of_file(dependencies_file) + + key = Key(bucket, dependencies_file_hash) + key.storage_class = 'REDUCED_REDUNDANCY' + + if mode == 'download': + download(directory) + elif mode == 'upload': + if isfile(NEED_TO_UPLOAD_MARKER): # FIXME + upload(directory) + else: + print("No need to upload anything.") + else: + raise SystemExit("Unrecognized mode {!r}".format(mode)) diff --git a/dist/bower_components/bootstrap/test-infra/sauce_browsers.yml b/dist/bower_components/bootstrap/test-infra/sauce_browsers.yml new file mode 100644 index 000000000..9ec9c4cb1 --- /dev/null +++ b/dist/bower_components/bootstrap/test-infra/sauce_browsers.yml @@ -0,0 +1,83 @@ +[ + # Docs: https://saucelabs.com/docs/platforms/webdriver + + { + browserName: "safari", + platform: "OS X 10.9" + }, + { + browserName: "chrome", + platform: "OS X 10.9", + version: "31" + }, + { + browserName: "firefox", + platform: "OS X 10.9" + }, + + # Mac Opera not currently supported by Sauce Labs + + { + browserName: "internet explorer", + version: "11", + platform: "Windows 8.1" + }, + { + browserName: "internet explorer", + version: "10", + platform: "Windows 8" + }, + # { + # browserName: "internet explorer", + # version: "9", + # platform: "Windows 7" + # }, + # { + # browserName: "internet explorer", + # version: "8", + # platform: "Windows 7" + # }, + + # { # Unofficial + # browserName: "internet explorer", + # version: "7", + # platform: "Windows XP" + # }, + + { + browserName: "chrome", + platform: "Windows 8.1" + }, + { + browserName: "firefox", + platform: "Windows 8.1" + }, + + # Win Opera 15+ not currently supported by Sauce Labs + + { + browserName: "iphone", + platform: "OS X 10.9", + version: "7" + }, + + # iOS Chrome not currently supported by Sauce Labs + + # Linux (unofficial) + { + browserName: "chrome", + platform: "Linux" + }, + { + browserName: "firefox", + platform: "Linux" + } + + # Android Chrome not currently supported by Sauce Labs + + # { # Android Browser (super-unofficial) + # browserName: "android", + # version: "4.0", + # platform: "Linux" + # } +] diff --git a/dist/bower_components/bootstrap/test-infra/shrinkwrap.js b/dist/bower_components/bootstrap/test-infra/shrinkwrap.js new file mode 100644 index 000000000..7a0328d41 --- /dev/null +++ b/dist/bower_components/bootstrap/test-infra/shrinkwrap.js @@ -0,0 +1,24 @@ +/* jshint node: true */ + +/* +This Grunt task updates the npm-shrinkwrap.canonical.json file that's used as the key for Bootstrap's npm packages cache. +This task should be run and the updated file should be committed whenever Bootstrap's dependencies change. +*/ + +var canonicallyJsonStringify = require('canonical-json'); +var NON_CANONICAL_FILE = 'npm-shrinkwrap.json'; +var DEST_FILE = 'test-infra/npm-shrinkwrap.canonical.json'; + + +function updateShrinkwrap(grunt) { + // Assumption: Non-canonical shrinkwrap already generated by prerequisite Grunt task + var shrinkwrapData = grunt.file.readJSON(NON_CANONICAL_FILE); + grunt.log.writeln('Deleting ' + NON_CANONICAL_FILE.cyan + '...'); + grunt.file.delete(NON_CANONICAL_FILE); + // Output as Canonical JSON in correct location + grunt.file.write(DEST_FILE, canonicallyJsonStringify(shrinkwrapData)); + grunt.log.writeln('File ' + DEST_FILE.cyan + ' updated.'); +} + + +module.exports = updateShrinkwrap; diff --git a/dist/bower_components/bootstrap/test-infra/uncached-npm-install.sh b/dist/bower_components/bootstrap/test-infra/uncached-npm-install.sh new file mode 100644 index 000000000..1c5624986 --- /dev/null +++ b/dist/bower_components/bootstrap/test-infra/uncached-npm-install.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cp test-infra/npm-shrinkwrap.canonical.json npm-shrinkwrap.json +npm install +rm npm-shrinkwrap.json diff --git a/dist/bower_components/es5-shim/.bower.json b/dist/bower_components/es5-shim/.bower.json new file mode 100644 index 000000000..146a31e82 --- /dev/null +++ b/dist/bower_components/es5-shim/.bower.json @@ -0,0 +1,14 @@ +{ + "name": "es5-shim", + "homepage": "https://github.com/es-shims/es5-shim", + "version": "2.1.0", + "_release": "2.1.0", + "_resolution": { + "type": "version", + "tag": "v2.1.0", + "commit": "07da727ff7db2a3a25d6bc25d13e374b3bbc99c2" + }, + "_source": "git://github.com/es-shims/es5-shim.git", + "_target": "~2.1.0", + "_originalSource": "es5-shim" +} \ No newline at end of file diff --git a/dist/bower_components/es5-shim/.gitignore b/dist/bower_components/es5-shim/.gitignore new file mode 100644 index 000000000..fd4f2b066 --- /dev/null +++ b/dist/bower_components/es5-shim/.gitignore @@ -0,0 +1,2 @@ +node_modules +.DS_Store diff --git a/dist/bower_components/es5-shim/CHANGES b/dist/bower_components/es5-shim/CHANGES new file mode 100644 index 000000000..f6f4f046e --- /dev/null +++ b/dist/bower_components/es5-shim/CHANGES @@ -0,0 +1,93 @@ + +2.0.0 + - Separate reliable shims from dubious shims (shams). + +1.2.10 + - Group-effort Style Cleanup + - Took a stab at fixing Object.defineProperty on IE8 without + bad side-effects. (@hax) + - Object.isExtensible no longer fakes it. (@xavierm) + - Date.prototype.toISOString no longer deals with partial + ISO dates, per spec (@kitcambridge) + - More (mostly from @bryanforbes) + +1.2.9 + - Corrections to toISOString by @kitcambridge + - Fixed three bugs in array methods revealed by Jasmine tests. + - Cleaned up Function.prototype.bind with more fixes and tests from + @bryanforbes. + +1.2.8 + - Actually fixed problems with Function.prototype.bind, and regressions + from 1.2.7 (@bryanforbes, @jdalton #36) + +1.2.7 - REGRESSED + - Fixed problems with Function.prototype.bind when called as a constructor. + (@jdalton #36) + +1.2.6 + - Revised Date.parse to match ES 5.1 (kitcambridge) + +1.2.5 + - Fixed a bug for padding it Date..toISOString (tadfisher issue #33) + +1.2.4 + - Fixed a descriptor bug in Object.defineProperty (raynos) + +1.2.3 + - Cleaned up RequireJS and + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dist/bower_components/es5-shim/tests/index.min.html b/dist/bower_components/es5-shim/tests/index.min.html new file mode 100644 index 000000000..65e590a32 --- /dev/null +++ b/dist/bower_components/es5-shim/tests/index.min.html @@ -0,0 +1,63 @@ + + + + Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dist/bower_components/es5-shim/tests/lib/jasmine-html.js b/dist/bower_components/es5-shim/tests/lib/jasmine-html.js new file mode 100644 index 000000000..73834010f --- /dev/null +++ b/dist/bower_components/es5-shim/tests/lib/jasmine-html.js @@ -0,0 +1,190 @@ +jasmine.TrivialReporter = function(doc) { + this.document = doc || document; + this.suiteDivs = {}; + this.logRunningSpecs = false; +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { el.appendChild(child); } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { + var showPassed, showSkipped; + + this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' }, + this.createDom('div', { className: 'banner' }, + this.createDom('div', { className: 'logo' }, + this.createDom('span', { className: 'title' }, "Jasmine"), + this.createDom('span', { className: 'version' }, runner.env.versionString())), + this.createDom('div', { className: 'options' }, + "Show ", + showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), + showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") + ) + ), + + this.runnerDiv = this.createDom('div', { className: 'runner running' }, + this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), + this.runnerMessageSpan = this.createDom('span', {}, "Running..."), + this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) + ); + + this.document.body.appendChild(this.outerDiv); + + var suites = runner.suites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + var suiteDiv = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), + this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); + this.suiteDivs[suite.id] = suiteDiv; + var parentDiv = this.outerDiv; + if (suite.parentSuite) { + parentDiv = this.suiteDivs[suite.parentSuite.id]; + } + parentDiv.appendChild(suiteDiv); + } + + this.startedAt = new Date(); + + var self = this; + showPassed.onclick = function(evt) { + if (showPassed.checked) { + self.outerDiv.className += ' show-passed'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); + } + }; + + showSkipped.onclick = function(evt) { + if (showSkipped.checked) { + self.outerDiv.className += ' show-skipped'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); + } + }; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + var results = runner.results(); + var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; + this.runnerDiv.setAttribute("class", className); + //do it twice for IE + this.runnerDiv.setAttribute("className", className); + var specs = runner.specs(); + var specCount = 0; + for (var i = 0; i < specs.length; i++) { + if (this.specFilter(specs[i])) { + specCount++; + } + } + var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); + message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; + this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); + + this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); +}; + +jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { + var results = suite.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.totalCount === 0) { // todo: change this to check results.skipped + status = 'skipped'; + } + this.suiteDivs[suite.id].className += " " + status; +}; + +jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { + if (this.logRunningSpecs) { + this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var results = spec.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + var specDiv = this.createDom('div', { className: 'spec ' + status }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(spec.getFullName()), + title: spec.getFullName() + }, spec.description)); + + + var resultItems = results.getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + specDiv.appendChild(messagesDiv); + } + + this.suiteDivs[spec.suite.id].appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } +}; + +jasmine.TrivialReporter.prototype.getLocation = function() { + return this.document.location; +}; + +jasmine.TrivialReporter.prototype.specFilter = function(spec) { + var paramMap = {}; + var params = this.getLocation().search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + if (!paramMap.spec) { + return true; + } + return spec.getFullName().indexOf(paramMap.spec) === 0; +}; diff --git a/dist/bower_components/es5-shim/tests/lib/jasmine.css b/dist/bower_components/es5-shim/tests/lib/jasmine.css new file mode 100644 index 000000000..6583fe7c6 --- /dev/null +++ b/dist/bower_components/es5-shim/tests/lib/jasmine.css @@ -0,0 +1,166 @@ +body { + font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; +} + + +.jasmine_reporter a:visited, .jasmine_reporter a { + color: #303; +} + +.jasmine_reporter a:hover, .jasmine_reporter a:active { + color: blue; +} + +.run_spec { + float:right; + padding-right: 5px; + font-size: .8em; + text-decoration: none; +} + +.jasmine_reporter { + margin: 0 5px; +} + +.banner { + color: #303; + background-color: #fef; + padding: 5px; +} + +.logo { + float: left; + font-size: 1.1em; + padding-left: 5px; +} + +.logo .version { + font-size: .6em; + padding-left: 1em; +} + +.runner.running { + background-color: yellow; +} + + +.options { + text-align: right; + font-size: .8em; +} + + + + +.suite { + border: 1px outset gray; + margin: 5px 0; + padding-left: 1em; +} + +.suite .suite { + margin: 5px; +} + +.suite.passed { + background-color: #dfd; +} + +.suite.failed { + background-color: #fdd; +} + +.spec { + margin: 5px; + padding-left: 1em; + clear: both; +} + +.spec.failed, .spec.passed, .spec.skipped { + padding-bottom: 5px; + border: 1px solid gray; +} + +.spec.failed { + background-color: #fbb; + border-color: red; +} + +.spec.passed { + background-color: #bfb; + border-color: green; +} + +.spec.skipped { + background-color: #bbb; +} + +.messages { + border-left: 1px dashed gray; + padding-left: 1em; + padding-right: 1em; +} + +.passed { + background-color: #cfc; + display: none; +} + +.failed { + background-color: #fbb; +} + +.skipped { + color: #777; + background-color: #eee; + display: none; +} + + +/*.resultMessage {*/ + /*white-space: pre;*/ +/*}*/ + +.resultMessage span.result { + display: block; + line-height: 2em; + color: black; +} + +.resultMessage .mismatch { + color: black; +} + +.stackTrace { + white-space: pre; + font-size: .8em; + margin-left: 10px; + max-height: 5em; + overflow: auto; + border: 1px inset red; + padding: 1em; + background: #eef; +} + +.finished-at { + padding-left: 1em; + font-size: .6em; +} + +.show-passed .passed, +.show-skipped .skipped { + display: block; +} + + +#jasmine_content { + position:fixed; + right: 100%; +} + +.runner { + border: 1px solid gray; + display: block; + margin: 5px 0; + padding: 2px 0 2px 10px; +} diff --git a/dist/bower_components/es5-shim/tests/lib/jasmine.js b/dist/bower_components/es5-shim/tests/lib/jasmine.js new file mode 100644 index 000000000..70d7d25e1 --- /dev/null +++ b/dist/bower_components/es5-shim/tests/lib/jasmine.js @@ -0,0 +1,2477 @@ +var isCommonJS = typeof window == "undefined"; + +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; +if (isCommonJS) exports.jasmine = jasmine; +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined is just + * a plain old variable and may be redefined by somebody else. + * + * @private + */ +jasmine.undefined = jasmine.___undefined___; + +/** + * Show diagnostic messages in the console if set to true + * + */ +jasmine.VERBOSE = false; + +/** + * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. + * + */ +jasmine.DEFAULT_UPDATE_INTERVAL = 250; + +/** + * Default timeout interval in milliseconds for waitsFor() blocks. + */ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + +jasmine.getGlobal = function() { + function getGlobal() { + return this; + } + + return getGlobal(); +}; + +/** + * Allows for bound functions to be compared. Internal use only. + * + * @ignore + * @private + * @param base {Object} bound 'this' for the function + * @param name {Function} function to find + */ +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + if (original.apply) { + return function() { + return original.apply(base, arguments); + }; + } else { + // IE support + return jasmine.getGlobal()[name]; + } +}; + +jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + +jasmine.MessageResult = function(values) { + this.type = 'log'; + this.values = values; + this.trace = new Error(); // todo: test better +}; + +jasmine.MessageResult.prototype.toString = function() { + var text = ""; + for (var i = 0; i < this.values.length; i++) { + if (i > 0) text += " "; + if (jasmine.isString_(this.values[i])) { + text += this.values[i]; + } else { + text += jasmine.pp(this.values[i]); + } + } + return text; +}; + +jasmine.ExpectationResult = function(params) { + this.type = 'expect'; + this.matcherName = params.matcherName; + this.passed_ = params.passed; + this.expected = params.expected; + this.actual = params.actual; + this.message = this.passed_ ? 'Passed.' : params.message; + + var trace = (params.trace || new Error(this.message)); + this.trace = this.passed_ ? '' : trace; +}; + +jasmine.ExpectationResult.prototype.toString = function () { + return this.message; +}; + +jasmine.ExpectationResult.prototype.passed = function () { + return this.passed_; +}; + +/** + * Getter for the Jasmine environment. Ensures one gets created + */ +jasmine.getEnv = function() { + var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + return env; +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isArray_ = function(value) { + return jasmine.isA_("Array", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isString_ = function(value) { + return jasmine.isA_("String", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isNumber_ = function(value) { + return jasmine.isA_("Number", value); +}; + +/** + * @ignore + * @private + * @param {String} typeName + * @param value + * @returns {Boolean} + */ +jasmine.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +}; + +/** + * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + * + * @param value {Object} an object to be outputted + * @returns {String} + */ +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +/** + * Returns true if the object is a DOM Node. + * + * @param {Object} obj object to check + * @returns {Boolean} + */ +jasmine.isDomNode = function(obj) { + return obj.nodeType > 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). + * + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).toHaveBeenCalled(); + * expect(foo.not).toHaveBeenCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { + throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the current spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.log = function() { + var spec = jasmine.getEnv().currentSpec; + spec.log.apply(spec, arguments); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @returns a Jasmine spy that can be chained with all spy methods + */ +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; +if (isCommonJS) exports.spyOn = spyOn; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; +if (isCommonJS) exports.it = it; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; +if (isCommonJS) exports.xit = xit; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * jasmine.Matchers functions. + * + * @param {Object} actual Actual value to test against and expected value + */ +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; +if (isCommonJS) exports.expect = expect; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; +if (isCommonJS) exports.runs = runs; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; +if (isCommonJS) exports.waits = waits; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); +}; +if (isCommonJS) exports.waitsFor = waitsFor; + +/** + * A function that is called before each spec in a suite. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; +if (isCommonJS) exports.beforeEach = beforeEach; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; +if (isCommonJS) exports.afterEach = afterEach; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; +if (isCommonJS) exports.describe = describe; + +/** + * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; +if (isCommonJS) exports.xdescribe = xdescribe; + + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; + } + + var xhr = tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP"); + }) || + tryIt(function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }); + + if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); + + return xhr; +} : XMLHttpRequest; +/** + * @namespace + */ +jasmine.util = {}; + +/** + * Declare that a child class inherit it's prototype from the parent class. + * + * @private + * @param {Function} childClass + * @param {Function} parentClass + */ +jasmine.util.inherit = function(childClass, parentClass) { + /** + * @private + */ + var subclass = function() { + }; + subclass.prototype = parentClass.prototype; + childClass.prototype = new subclass(); +}; + +jasmine.util.formatException = function(e) { + var lineNumber; + if (e.line) { + lineNumber = e.line; + } + else if (e.lineNumber) { + lineNumber = e.lineNumber; + } + + var file; + + if (e.sourceURL) { + file = e.sourceURL; + } + else if (e.fileName) { + file = e.fileName; + } + + var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + + if (file && lineNumber) { + message += ' in ' + file + ' (line ' + lineNumber + ')'; + } + + return message; +}; + +jasmine.util.htmlEscape = function(str) { + if (!str) return str; + return str.replace(/&/g, '&') + .replace(//g, '>'); +}; + +jasmine.util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); + return arrayOfArgs; +}; + +jasmine.util.extend = function(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; +}; + +/** + * Environment for Jasmine + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner_ = new jasmine.Runner(this); + + this.reporter = new jasmine.MultiReporter(); + + this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; + this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.nextSuiteId_ = 0; + this.equalityTesters_ = []; + + // wrap matchers + this.matchersClass = function() { + jasmine.Matchers.apply(this, arguments); + }; + jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + + jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +/** + * @returns an object containing jasmine version build info, if set. + */ +jasmine.Env.prototype.version = function () { + if (jasmine.version_) { + return jasmine.version_; + } else { + throw new Error('Version not set'); + } +}; + +/** + * @returns string containing jasmine version build info, if set. + */ +jasmine.Env.prototype.versionString = function() { + if (!jasmine.version_) { + return "version unknown"; + } + + var version = this.version(); + var versionString = version.major + "." + version.minor + "." + version.build; + if (version.release_candidate) { + versionString += ".rc" + version.release_candidate + } + versionString += " revision " + version.revision; + return versionString; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSpecId = function () { + return this.nextSpecId_++; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSuiteId = function () { + return this.nextSuiteId_++; +}; + +/** + * Register a reporter to receive status updates from Jasmine. + * @param {jasmine.Reporter} reporter An object which will receive status updates. + */ +jasmine.Env.prototype.addReporter = function(reporter) { + this.reporter.addReporter(reporter); +}; + +jasmine.Env.prototype.execute = function() { + this.currentRunner_.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.add(suite); + } else { + this.currentRunner_.add(suite); + } + + this.currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch(e) { + declarationError = e; + } + + if (declarationError) { + this.it("encountered a declaration exception", function() { + throw declarationError; + }); + } + + this.currentSuite = parentSuite; + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + if (this.currentSuite) { + this.currentSuite.beforeEach(beforeEachFunction); + } else { + this.currentRunner_.beforeEach(beforeEachFunction); + } +}; + +jasmine.Env.prototype.currentRunner = function () { + return this.currentRunner_; +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + if (this.currentSuite) { + this.currentSuite.afterEach(afterEachFunction); + } else { + this.currentRunner_.afterEach(afterEachFunction); + } + +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.add(spec); + this.currentSpec = spec; + + if (func) { + spec.runs(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId(), + runs: function() { + } + }; +}; + +jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { + return true; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj !== null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== jasmine.undefined) return result; + } + + if (a === b) return true; + + if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { + return (a == jasmine.undefined && b == jasmine.undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a instanceof jasmine.Matchers.Any) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.Any) { + return b.matches(a); + } + + if (jasmine.isString_(a) && jasmine.isString_(b)) { + return (a == b); + } + + if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { + return (a == b); + } + + if (typeof a === "object" && typeof b === "object") { + return this.compareObjects_(a, b, mismatchKeys, mismatchValues); + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; +/** No-op base class for Jasmine reporters. + * + * @constructor + */ +jasmine.Reporter = function() { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecStarting = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecResults = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.log = function(str) { +}; + +/** + * Blocks are functions with executable code that make up a spec. + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {jasmine.Spec} spec + */ +jasmine.Block = function(env, func, spec) { + this.env = env; + this.func = func; + this.spec = spec; +}; + +jasmine.Block.prototype.execute = function(onComplete) { + try { + this.func.apply(this.spec); + } catch (e) { + this.spec.fail(e); + } + onComplete(); +}; +/** JavaScript API reporter. + * + * @constructor + */ +jasmine.JsApiReporter = function() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; +}; + +jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } +}; + +jasmine.JsApiReporter.prototype.suites = function() { + return this.suites_; +}; + +jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; +}; + +jasmine.JsApiReporter.prototype.results = function() { + return this.results_; +}; + +jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { + this.results_[spec.id] = { + messages: spec.results().getItems(), + result: spec.results().failedCount > 0 ? "failed" : "passed" + }; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.log = function(str) { +}; + +jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; +}; + +jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; +}; + +/** + * @constructor + * @param {jasmine.Env} env + * @param actual + * @param {jasmine.Spec} spec + */ +jasmine.Matchers = function(env, actual, spec, opt_isNot) { + this.env = env; + this.actual = actual; + this.spec = spec; + this.isNot = opt_isNot || false; + this.reportWasCalled_ = false; +}; + +// todo: @deprecated as of Jasmine 0.11, remove soon [xw] +jasmine.Matchers.pp = function(str) { + throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); +}; + +// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); +}; + +jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { + for (var methodName in prototype) { + if (methodName == 'report') continue; + var orig = prototype[methodName]; + matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); + } +}; + +jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { + return function() { + var matcherArgs = jasmine.util.argsToArray(arguments); + var result = matcherFunction.apply(this, arguments); + + if (this.isNot) { + result = !result; + } + + if (this.reportWasCalled_) return result; + + var message; + if (!result) { + if (this.message) { + message = this.message.apply(this, arguments); + if (jasmine.isArray_(message)) { + message = message[this.isNot ? 1 : 0]; + } + } else { + var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; + if (matcherArgs.length > 0) { + for (var i = 0; i < matcherArgs.length; i++) { + if (i > 0) message += ","; + message += " " + jasmine.pp(matcherArgs[i]); + } + } + message += "."; + } + } + var expectationResult = new jasmine.ExpectationResult({ + matcherName: matcherName, + passed: result, + expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], + actual: this.actual, + message: message + }); + this.spec.addMatcherResult(expectationResult); + return jasmine.undefined; + }; +}; + + + + +/** + * toBe: compares the actual to the expected using === + * @param expected + */ +jasmine.Matchers.prototype.toBe = function(expected) { + return this.actual === expected; +}; + +/** + * toNotBe: compares the actual to the expected using !== + * @param expected + * @deprecated as of 1.0. Use not.toBe() instead. + */ +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.actual !== expected; +}; + +/** + * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. + * + * @param expected + */ +jasmine.Matchers.prototype.toEqual = function(expected) { + return this.env.equals_(this.actual, expected); +}; + +/** + * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual + * @param expected + * @deprecated as of 1.0. Use not.toNotEqual() instead. + */ +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return !this.env.equals_(this.actual, expected); +}; + +/** + * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes + * a pattern or a String. + * + * @param expected + */ +jasmine.Matchers.prototype.toMatch = function(expected) { + return new RegExp(expected).test(this.actual); +}; + +/** + * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch + * @param expected + * @deprecated as of 1.0. Use not.toMatch() instead. + */ +jasmine.Matchers.prototype.toNotMatch = function(expected) { + return !(new RegExp(expected).test(this.actual)); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeDefined = function() { + return (this.actual !== jasmine.undefined); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeUndefined = function() { + return (this.actual === jasmine.undefined); +}; + +/** + * Matcher that compares the actual to null. + */ +jasmine.Matchers.prototype.toBeNull = function() { + return (this.actual === null); +}; + +/** + * Matcher that boolean not-nots the actual. + */ +jasmine.Matchers.prototype.toBeTruthy = function() { + return !!this.actual; +}; + + +/** + * Matcher that boolean nots the actual. + */ +jasmine.Matchers.prototype.toBeFalsy = function() { + return !this.actual; +}; + + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called. + */ +jasmine.Matchers.prototype.toHaveBeenCalled = function() { + if (arguments.length > 0) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to have been called.", + "Expected spy " + this.actual.identity + " not to have been called." + ]; + }; + + return this.actual.wasCalled; +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ +jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was not called. + * + * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead + */ +jasmine.Matchers.prototype.wasNotCalled = function() { + if (arguments.length > 0) { + throw new Error('wasNotCalled does not take arguments'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to not have been called.", + "Expected spy " + this.actual.identity + " to have been called." + ]; + }; + + return !this.actual.wasCalled; +}; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. + * + * @example + * + */ +jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + this.message = function() { + if (this.actual.callCount === 0) { + // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was." + ]; + } else { + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) + ]; + } + }; + + return this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + +/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasNotCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" + ]; + }; + + return !this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** + * Matcher that checks that the expected item is an element in the actual Array. + * + * @param {Object} expected + */ +jasmine.Matchers.prototype.toContain = function(expected) { + return this.env.contains_(this.actual, expected); +}; + +/** + * Matcher that checks that the expected item is NOT an element in the actual Array. + * + * @param {Object} expected + * @deprecated as of 1.0. Use not.toNotContain() instead. + */ +jasmine.Matchers.prototype.toNotContain = function(expected) { + return !this.env.contains_(this.actual, expected); +}; + +jasmine.Matchers.prototype.toBeLessThan = function(expected) { + return this.actual < expected; +}; + +jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { + return this.actual > expected; +}; + +/** + * Matcher that checks that the expected item is equal to the actual item + * up to a given level of decimal precision (default 2). + * + * @param {Number} expected + * @param {Number} precision + */ +jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { + if (!(precision === 0)) { + precision = precision || 2; + } + var multiplier = Math.pow(10, precision); + var actual = Math.round(this.actual * multiplier); + expected = Math.round(expected * multiplier); + return expected == actual; +}; + +/** + * Matcher that checks that the expected exception was thrown by the actual. + * + * @param {String} expected + */ +jasmine.Matchers.prototype.toThrow = function(expected) { + var result = false; + var exception; + if (typeof this.actual != 'function') { + throw new Error('Actual is not a function'); + } + try { + this.actual(); + } catch (e) { + exception = e; + } + if (exception) { + result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); + } + + var not = this.isNot ? "not " : ""; + + this.message = function() { + if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { + return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); + } else { + return "Expected function to throw an exception."; + } + }; + + return result; +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.matches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.toString = function() { + return ''; +}; + +/** + * @constructor + */ +jasmine.MultiReporter = function() { + this.subReporters_ = []; +}; +jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + +jasmine.MultiReporter.prototype.addReporter = function(reporter) { + this.subReporters_.push(reporter); +}; + +(function() { + var functionNames = [ + "reportRunnerStarting", + "reportRunnerResults", + "reportSuiteResults", + "reportSpecStarting", + "reportSpecResults", + "log" + ]; + for (var i = 0; i < functionNames.length; i++) { + var functionName = functionNames[i]; + jasmine.MultiReporter.prototype[functionName] = (function(functionName) { + return function() { + for (var j = 0; j < this.subReporters_.length; j++) { + var subReporter = this.subReporters_[j]; + if (subReporter[functionName]) { + subReporter[functionName].apply(subReporter, arguments); + } + } + }; + })(functionName); + } +})(); +/** + * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + /** + * The total count of results + */ + this.totalCount = 0; + /** + * Number of passed results + */ + this.passedCount = 0; + /** + * Number of failed results + */ + this.failedCount = 0; + /** + * Was this suite/spec skipped? + */ + this.skipped = false; + /** + * @ignore + */ + this.items_ = []; +}; + +/** + * Roll up the result counts. + * + * @param result + */ +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +/** + * Adds a log message. + * @param values Array of message parts which will be concatenated later. + */ +jasmine.NestedResults.prototype.log = function(values) { + this.items_.push(new jasmine.MessageResult(values)); +}; + +/** + * Getter for the results: message & results. + */ +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * Adds a result, tracking counts (total, passed, & failed) + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'log') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed()) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +/** + * @returns {Boolean} True if everything below passed + */ +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; +/** + * Base class for pretty printing for expectation results. + */ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +/** + * Formats a value in a nice, human-readable string. + * + * @param value + */ +jasmine.PrettyPrinter.prototype.format = function(value) { + if (this.ppNestLevel_ > 40) { + throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); + } + + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar(''); + } else if (value instanceof jasmine.Matchers.Any) { + this.emitScalar(value.toString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (jasmine.isSpy(value)) { + this.emitScalar("spy on " + value.identity); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (property == '__Jasmine_been_here_before__') continue; + fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && + obj.__lookupGetter__(property) !== null) : false); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitString = function(value) { + this.append("'" + value + "'"); +}; + +jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + this.append('[ '); + for (var i = 0; i < array.length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; +jasmine.Queue = function(env) { + this.env = env; + this.blocks = []; + this.running = false; + this.index = 0; + this.offset = 0; + this.abort = false; +}; + +jasmine.Queue.prototype.addBefore = function(block) { + this.blocks.unshift(block); +}; + +jasmine.Queue.prototype.add = function(block) { + this.blocks.push(block); +}; + +jasmine.Queue.prototype.insertNext = function(block) { + this.blocks.splice((this.index + this.offset + 1), 0, block); + this.offset++; +}; + +jasmine.Queue.prototype.start = function(onComplete) { + this.running = true; + this.onComplete = onComplete; + this.next_(); +}; + +jasmine.Queue.prototype.isRunning = function() { + return this.running; +}; + +jasmine.Queue.LOOP_DONT_RECURSE = true; + +jasmine.Queue.prototype.next_ = function() { + var self = this; + var goAgain = true; + + while (goAgain) { + goAgain = false; + + if (self.index < self.blocks.length && !this.abort) { + var calledSynchronously = true; + var completedSynchronously = false; + + var onComplete = function () { + if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { + completedSynchronously = true; + return; + } + + if (self.blocks[self.index].abort) { + self.abort = true; + } + + self.offset = 0; + self.index++; + + var now = new Date().getTime(); + if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { + self.env.lastUpdate = now; + self.env.setTimeout(function() { + self.next_(); + }, 0); + } else { + if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { + goAgain = true; + } else { + self.next_(); + } + } + }; + self.blocks[self.index].execute(onComplete); + + calledSynchronously = false; + if (completedSynchronously) { + onComplete(); + } + + } else { + self.running = false; + if (self.onComplete) { + self.onComplete(); + } + } + } +}; + +jasmine.Queue.prototype.results = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.blocks.length; i++) { + if (this.blocks[i].results) { + results.addResult(this.blocks[i].results()); + } + } + return results; +}; + + +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + var self = this; + self.env = env; + self.queue = new jasmine.Queue(env); + self.before_ = []; + self.after_ = []; + self.suites_ = []; +}; + +jasmine.Runner.prototype.execute = function() { + var self = this; + if (self.env.reporter.reportRunnerStarting) { + self.env.reporter.reportRunnerStarting(this); + } + self.queue.start(function () { + self.finishCallback(); + }); +}; + +jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.splice(0,0,beforeEachFunction); +}; + +jasmine.Runner.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.splice(0,0,afterEachFunction); +}; + + +jasmine.Runner.prototype.finishCallback = function() { + this.env.reporter.reportRunnerResults(this); +}; + +jasmine.Runner.prototype.addSuite = function(suite) { + this.suites_.push(suite); +}; + +jasmine.Runner.prototype.add = function(block) { + if (block instanceof jasmine.Suite) { + this.addSuite(block); + } + this.queue.add(block); +}; + +jasmine.Runner.prototype.specs = function () { + var suites = this.suites(); + var specs = []; + for (var i = 0; i < suites.length; i++) { + specs = specs.concat(suites[i].specs()); + } + return specs; +}; + +jasmine.Runner.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Runner.prototype.topLevelSuites = function() { + var topLevelSuites = []; + for (var i = 0; i < this.suites_.length; i++) { + if (!this.suites_[i].parentSuite) { + topLevelSuites.push(this.suites_[i]); + } + } + return topLevelSuites; +}; + +jasmine.Runner.prototype.results = function() { + return this.queue.results(); +}; +/** + * Internal representation of a Jasmine specification, or test. + * + * @constructor + * @param {jasmine.Env} env + * @param {jasmine.Suite} suite + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + if (!env) { + throw new Error('jasmine.Env() required'); + } + if (!suite) { + throw new Error('jasmine.Suite() required'); + } + var spec = this; + spec.id = env.nextSpecId ? env.nextSpecId() : null; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(env); + + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results_ = new jasmine.NestedResults(); + spec.results_.description = description; + spec.matchersClass = null; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + + +jasmine.Spec.prototype.results = function() { + return this.results_; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.Spec.prototype.log = function() { + return this.results_.log(arguments); +}; + +jasmine.Spec.prototype.runs = function (func) { + var block = new jasmine.Block(this.env, func, this); + this.addToQueue(block); + return this; +}; + +jasmine.Spec.prototype.addToQueue = function (block) { + if (this.queue.isRunning()) { + this.queue.insertNext(block); + } else { + this.queue.add(block); + } +}; + +/** + * @param {jasmine.ExpectationResult} result + */ +jasmine.Spec.prototype.addMatcherResult = function(result) { + this.results_.addResult(result); +}; + +jasmine.Spec.prototype.expect = function(actual) { + var positive = new (this.getMatchersClass_())(this.env, actual, this); + positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); + return positive; +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +jasmine.Spec.prototype.waits = function(timeout) { + var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); + this.addToQueue(waitsFunc); + return this; +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + var latchFunction_ = null; + var optional_timeoutMessage_ = null; + var optional_timeout_ = null; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + switch (typeof arg) { + case 'function': + latchFunction_ = arg; + break; + case 'string': + optional_timeoutMessage_ = arg; + break; + case 'number': + optional_timeout_ = arg; + break; + } + } + + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); + this.addToQueue(waitsForFunc); + return this; +}; + +jasmine.Spec.prototype.fail = function (e) { + var expectationResult = new jasmine.ExpectationResult({ + passed: false, + message: e ? jasmine.util.formatException(e) : 'Exception', + trace: { stack: e.stack } + }); + this.results_.addResult(expectationResult); +}; + +jasmine.Spec.prototype.getMatchersClass_ = function() { + return this.matchersClass || this.env.matchersClass; +}; + +jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { + var parent = this.getMatchersClass_(); + var newMatchersClass = function() { + parent.apply(this, arguments); + }; + jasmine.util.inherit(newMatchersClass, parent); + jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); + this.matchersClass = newMatchersClass; +}; + +jasmine.Spec.prototype.finishCallback = function() { + this.env.reporter.reportSpecResults(this); +}; + +jasmine.Spec.prototype.finish = function(onComplete) { + this.removeAllSpies(); + this.finishCallback(); + if (onComplete) { + onComplete(); + } +}; + +jasmine.Spec.prototype.after = function(doAfter) { + if (this.queue.isRunning()) { + this.queue.add(new jasmine.Block(this.env, doAfter, this)); + } else { + this.afterCallbacks.unshift(doAfter); + } +}; + +jasmine.Spec.prototype.execute = function(onComplete) { + var spec = this; + if (!spec.env.specFilter(spec)) { + spec.results_.skipped = true; + spec.finish(onComplete); + return; + } + + this.env.reporter.reportSpecStarting(this); + + spec.env.currentSpec = spec; + + spec.addBeforesAndAftersToQueue(); + + spec.queue.start(function () { + spec.finish(onComplete); + }); +}; + +jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { + var runner = this.env.currentRunner(); + var i; + + for (var suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); + } + } + for (i = 0; i < runner.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); + } + for (i = 0; i < this.afterCallbacks.length; i++) { + this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); + } + for (suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, suite.after_[i], this)); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == jasmine.undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + +/** + * Internal representation of a Jasmine suite. + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + var self = this; + self.id = env.nextSuiteId ? env.nextSuiteId() : null; + self.description = description; + self.queue = new jasmine.Queue(env); + self.parentSuite = parentSuite; + self.env = env; + self.before_ = []; + self.after_ = []; + self.children_ = []; + self.suites_ = []; + self.specs_ = []; +}; + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finish = function(onComplete) { + this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (typeof(onComplete) == 'function') { + onComplete(); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.unshift(beforeEachFunction); +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.unshift(afterEachFunction); +}; + +jasmine.Suite.prototype.results = function() { + return this.queue.results(); +}; + +jasmine.Suite.prototype.add = function(suiteOrSpec) { + this.children_.push(suiteOrSpec); + if (suiteOrSpec instanceof jasmine.Suite) { + this.suites_.push(suiteOrSpec); + this.env.currentRunner().addSuite(suiteOrSpec); + } else { + this.specs_.push(suiteOrSpec); + } + this.queue.add(suiteOrSpec); +}; + +jasmine.Suite.prototype.specs = function() { + return this.specs_; +}; + +jasmine.Suite.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Suite.prototype.children = function() { + return this.children_; +}; + +jasmine.Suite.prototype.execute = function(onComplete) { + var self = this; + this.queue.start(function () { + self.finish(onComplete); + }); +}; +jasmine.WaitsBlock = function(env, timeout, spec) { + this.timeout = timeout; + jasmine.Block.call(this, env, null, spec); +}; + +jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + +jasmine.WaitsBlock.prototype.execute = function (onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); + } + this.env.setTimeout(function () { + onComplete(); + }, this.timeout); +}; +/** + * A block which waits for some condition to become true, with timeout. + * + * @constructor + * @extends jasmine.Block + * @param {jasmine.Env} env The Jasmine environment. + * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. + * @param {Function} latchFunction A function which returns true when the desired condition has been met. + * @param {String} message The message to display if the desired condition hasn't been met within the given time period. + * @param {jasmine.Spec} spec The Jasmine spec. + */ +jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { + this.timeout = timeout || env.defaultTimeoutInterval; + this.latchFunction = latchFunction; + this.message = message; + this.totalTimeSpentWaitingForLatch = 0; + jasmine.Block.call(this, env, null, spec); +}; +jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + +jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + +jasmine.WaitsForBlock.prototype.execute = function(onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); + } + var latchFunctionResult; + try { + latchFunctionResult = this.latchFunction.apply(this.spec); + } catch (e) { + this.spec.fail(e); + onComplete(); + return; + } + + if (latchFunctionResult) { + onComplete(); + } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { + var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); + this.spec.fail({ + name: 'timeout', + message: message + }); + + this.abort = true; + onComplete(); + } else { + this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; + var self = this; + this.env.setTimeout(function() { + self.execute(onComplete); + }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + } +}; +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != jasmine.undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = jasmine.undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + +/** + * @namespace + */ +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + if (!jasmine.Clock.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + } + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: jasmine.getGlobal().setTimeout, + clearTimeout: jasmine.getGlobal().clearTimeout, + setInterval: jasmine.getGlobal().setInterval, + clearInterval: jasmine.getGlobal().clearInterval + }, + + assertInstalled: function() { + if (!jasmine.Clock.isInstalled()) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + isInstalled: function() { + return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +//else for IE support +jasmine.getGlobal().setTimeout = function(funcToCall, millis) { + if (jasmine.Clock.installed.setTimeout.apply) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.setTimeout(funcToCall, millis); + } +}; + +jasmine.getGlobal().setInterval = function(funcToCall, millis) { + if (jasmine.Clock.installed.setInterval.apply) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.setInterval(funcToCall, millis); + } +}; + +jasmine.getGlobal().clearTimeout = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearTimeout(timeoutKey); + } +}; + +jasmine.getGlobal().clearInterval = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearInterval(timeoutKey); + } +}; + +jasmine.version_= { + "major": 1, + "minor": 1, + "build": 0, + "revision": 1308618948, + "release_candidate": 1 +}; diff --git a/dist/bower_components/es5-shim/tests/lib/jasmine_favicon.png b/dist/bower_components/es5-shim/tests/lib/jasmine_favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..218f3b43713598fa5a3e78b57aceb909c33f46df GIT binary patch literal 905 zcmV;419tq0P)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_0008u zNkl3{fod28|PjmA)7fYg4w8-(2my9xtBGOs}K`n&t1VzxMO^X)M zrW+Ln1udc?q6TP)z5gAjt)P&D!M$+HJK#x<`xnD030zwD?KrxxY!2tlA zGc-58?0D7SsT)7Km=v+tNVNUk`?s@;^OxCF)y6P}_mL;~7;S<@b|MzmKq)m8l@yky zT1~ECpxZw@64!nkI34QLiUsA%i%N>-$&zGYR7WJyi9ERMyS(%kf z7A_r)X>!90&m(FwDQZ>q;+nOa*KR2+E6Fz)QwU=W1Oyo*4>_qlm|~joa|{4_A_3W8 z#FFZzRp-xMIx5a7D_Fj3&#r^TbIY@cND1d0f*^qDIs{!pw!IWGQ_%l4#ASm_D5Vet z0%ek7^)@xPihX_G0&hIc9*14ca=D!8oG}vW?H%~w^F?f_s>zU|fKrNJXJ_d6{v!t( zpEoqMws_yQws>3o?VW8Txq~#->dJG^ELW5irR!s`(_JvD^6;r+ho~eIK@ia8_lH(h zt*-p?CFC1_h2MV=?jP){uW!7WjLjCaO&c1D+tf582!XEaoB#xWAYcN5f$sLtf$koW zQs{{>)ZTq?FC6|J_%n}AWbiFK(Bo-%^-{H`*)E(ucjo-r%SYm)W5f6tN=xz=S646E fNXW#U{x?4WXWJ 3; + }); + expect(arr).toEqual([1,2,3,4,5,6]); + expect(i).toBe(3); + }); + it('should set the right context when given none', function() { + var context; + [1].some(function() {context = this;}); + expect(context).toBe(function() {return this}.call()); + }); + + it('should return false if it runs to the end', function() { + actual = testSubject.some(function() {}); + expect(actual).toBeFalsy(); + }); + it('should return true if it is stopped somewhere', function() { + actual = testSubject.some(function() { return true; }); + expect(actual).toBeTruthy(); + }); + it('should return false if there are no elements', function() { + actual = [].some(function() { return true; }); + expect(actual).toBeFalsy(); + }); + + it('should stop after 3 elements', function() { + testSubject.some(function(obj, index) { + actual[index] = obj; + numberOfRuns += 1; + if(numberOfRuns == 3) { + return true; + } + return false; + }); + expect(actual).toExactlyMatch(expected); + }); + it('should stop after 3 elements using a context', function() { + var o = { a: actual }; + testSubject.some(function(obj, index) { + this.a[index] = obj; + numberOfRuns += 1; + if(numberOfRuns == 3) { + return true; + } + return false; + }, o); + expect(actual).toExactlyMatch(expected); + }); + + it('should stop after 3 elements in an array-like object', function() { + var ts = createArrayLikeFromArray(testSubject); + Array.prototype.some.call(ts, function(obj, index) { + actual[index] = obj; + numberOfRuns += 1; + if(numberOfRuns == 3) { + return true; + } + return false; + }); + expect(actual).toExactlyMatch(expected); + }); + it('should stop after 3 elements in an array-like object using a context', function() { + var ts = createArrayLikeFromArray(testSubject); + var o = { a: actual }; + Array.prototype.some.call(ts, function(obj, index) { + this.a[index] = obj; + numberOfRuns += 1; + if(numberOfRuns == 3) { + return true; + } + return false; + }, o); + expect(actual).toExactlyMatch(expected); + }); + }); + describe('every', function() { + var actual, expected, numberOfRuns; + + beforeEach(function() { + expected = {0:2, 2: undefined, 3:true }; + actual = {}; + numberOfRuns = 0; + }); + + it('should pass the correct values along to the callback', function() { + var callback = jasmine.createSpy('callback'); + var array = ['1']; + array.every(callback); + expect(callback).toHaveBeenCalledWith('1', 0, array); + }); + it('should not affect elements added to the array after it has begun', function() { + var arr = [1,2,3], + i = 0; + arr.every(function(a) { + i++; + arr.push(a+3); + return i <= 3; + }); + expect(arr).toEqual([1,2,3,4,5,6]); + expect(i).toBe(3); + }); + it('should set the right context when given none', function() { + var context; + [1].every(function() {context = this;}); + expect(context).toBe(function() {return this}.call()); + }); + + it('should return true if the array is empty', function() { + actual = [].every(function() { return true; }); + expect(actual).toBeTruthy(); + + actual = [].every(function() { return false; }); + expect(actual).toBeTruthy(); + }); + it('should return true if it runs to the end', function() { + actual = [1,2,3].every(function() { return true; }); + expect(actual).toBeTruthy(); + }); + it('should return false if it is stopped before the end', function() { + actual = [1,2,3].every(function() { return false; }); + expect(actual).toBeFalsy(); + }); + + it('should return after 3 elements', function() { + testSubject.every(function(obj, index) { + actual[index] = obj; + numberOfRuns += 1; + if(numberOfRuns == 3) { + return false; + } + return true; + }); + expect(actual).toExactlyMatch(expected); + }); + it('should stop after 3 elements using a context', function() { + var o = { a: actual }; + testSubject.every(function(obj, index) { + this.a[index] = obj; + numberOfRuns += 1; + if(numberOfRuns == 3) { + return false; + } + return true; + }, o); + expect(actual).toExactlyMatch(expected); + }); + + it('should stop after 3 elements in an array-like object', function() { + var ts = createArrayLikeFromArray(testSubject); + Array.prototype.every.call(ts, function(obj, index) { + actual[index] = obj; + numberOfRuns += 1; + if(numberOfRuns == 3) { + return false; + } + return true; + }); + expect(actual).toExactlyMatch(expected); + }); + it('should stop after 3 elements in an array-like object using a context', function() { + var ts = createArrayLikeFromArray(testSubject); + var o = { a: actual }; + Array.prototype.every.call(ts, function(obj, index) { + this.a[index] = obj; + numberOfRuns += 1; + if(numberOfRuns == 3) { + return false; + } + return true; + }, o); + expect(actual).toExactlyMatch(expected); + }); + }); + + describe('indexOf', function() { + "use strict"; + var actual, expected, testSubject; + + beforeEach(function() { + testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0]; + delete testSubject[1]; + + }); + + it('should find the element', function() { + expected = 4; + actual = testSubject.indexOf('hej'); + expect(actual).toEqual(expected); + }); + it('should not find the element', function() { + expected = -1; + actual = testSubject.indexOf('mus'); + expect(actual).toEqual(expected); + }); + it('should find undefined as well', function() { + expected = -1; + actual = testSubject.indexOf(undefined); + expect(actual).not.toEqual(expected); + }); + it('should skip unset indexes', function() { + expected = 2; + actual = testSubject.indexOf(undefined); + expect(actual).toEqual(expected); + }); + it('should use a strict test', function() { + actual = testSubject.indexOf(null); + expect(actual).toEqual(5); + + actual = testSubject.indexOf('2'); + expect(actual).toEqual(-1); + }); + it('should skip the first if fromIndex is set', function() { + expect(testSubject.indexOf(2, 2)).toEqual(6); + expect(testSubject.indexOf(2, 0)).toEqual(0); + expect(testSubject.indexOf(2, 6)).toEqual(6); + }); + it('should work with negative fromIndex', function() { + expect(testSubject.indexOf(2, -3)).toEqual(6); + expect(testSubject.indexOf(2, -9)).toEqual(0); + }); + it('should work with fromIndex being greater than the length', function() { + expect(testSubject.indexOf(0, 20)).toEqual(-1); + }); + it('should work with fromIndex being negative and greater than the length', function() { + expect(testSubject.indexOf('hej', -20)).toEqual(4); + }); + + describe('Array-like', function ArrayLike() { + var indexOf = Array.prototype.indexOf, + testAL; + beforeEach(function beforeEach() { + testAL = {}; + testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0]; + testSubject.forEach(function (o,i) { + testAL[i] = o; + }); + testAL.length = testSubject.length; + }); + it('should find the element (array-like)', function() { + expected = 4; + actual = indexOf.call(testAL, 'hej'); + expect(actual).toEqual(expected); + }); + it('should not find the element (array-like)', function() { + expected = -1; + actual = indexOf.call(testAL, 'mus'); + expect(actual).toEqual(expected); + }); + it('should find undefined as well (array-like)', function() { + expected = -1; + actual = indexOf.call(testAL, undefined); + expect(actual).not.toEqual(expected); + }); + it('should skip unset indexes (array-like)', function() { + expected = 2; + actual = indexOf.call(testAL, undefined); + expect(actual).toEqual(expected); + }); + it('should use a strict test (array-like)', function() { + actual = Array.prototype.indexOf.call(testAL, null); + expect(actual).toEqual(5); + + actual = Array.prototype.indexOf.call(testAL, '2'); + expect(actual).toEqual(-1); + }); + it('should skip the first if fromIndex is set (array-like)', function() { + expect(indexOf.call(testAL, 2, 2)).toEqual(6); + expect(indexOf.call(testAL, 2, 0)).toEqual(0); + expect(indexOf.call(testAL, 2, 6)).toEqual(6); + }); + it('should work with negative fromIndex (array-like)', function() { + expect(indexOf.call(testAL, 2, -3)).toEqual(6); + expect(indexOf.call(testAL, 2, -9)).toEqual(0); + }); + it('should work with fromIndex being greater than the length (array-like)', function() { + expect(indexOf.call(testAL, 0, 20)).toEqual(-1); + }); + it('should work with fromIndex being negative and greater than the length (array-like)', function() { + expect(indexOf.call(testAL, 'hej', -20)).toEqual(4); + }); + }); + }); + describe('lastIndexOf', function() { + "use strict"; + var actual, expected, testSubject, testAL; + + beforeEach(function() { + testSubject = [2, 3, undefined, true, 'hej', null, 2, 3, false, 0]; + delete testSubject[1]; + delete testSubject[7]; + }); + describe('Array', function() { + it('should find the element', function() { + expected = 4; + actual = testSubject.lastIndexOf('hej'); + expect(actual).toEqual(expected); + }); + it('should not find the element', function() { + expected = -1; + actual = testSubject.lastIndexOf('mus'); + expect(actual).toEqual(expected); + }); + it('should find undefined as well', function() { + expected = -1; + actual = testSubject.lastIndexOf(undefined); + expect(actual).not.toEqual(expected); + }); + it('should skip unset indexes', function() { + expected = 2; + actual = testSubject.lastIndexOf(undefined); + expect(actual).toEqual(expected); + }); + it('should use a strict test', function() { + actual = testSubject.lastIndexOf(null); + expect(actual).toEqual(5); + + actual = testSubject.lastIndexOf('2'); + expect(actual).toEqual(-1); + }); + it('should skip the first if fromIndex is set', function() { + expect(testSubject.lastIndexOf(2, 2)).toEqual(0); + expect(testSubject.lastIndexOf(2, 0)).toEqual(0); + expect(testSubject.lastIndexOf(2, 6)).toEqual(6); + }); + it('should work with negative fromIndex', function() { + expect(testSubject.lastIndexOf(2, -3)).toEqual(6); + expect(testSubject.lastIndexOf(2, -9)).toEqual(0); + }); + it('should work with fromIndex being greater than the length', function() { + expect(testSubject.lastIndexOf(2, 20)).toEqual(6); + }); + it('should work with fromIndex being negative and greater than the length', function() { + expect(testSubject.lastIndexOf(2, -20)).toEqual(-1); + }); + }); + + describe('Array like', function() { + var lastIndexOf = Array.prototype.lastIndexOf, + testAL; + beforeEach(function() { + testAL = {}; + testSubject.forEach(function (o,i) { + testAL[i] = o; + }); + testAL.length = testSubject.length; + }); + it('should find the element (array-like)', function() { + expected = 4; + actual = lastIndexOf.call(testAL, 'hej'); + expect(actual).toEqual(expected); + }); + it('should not find the element (array-like)', function() { + expected = -1; + actual = lastIndexOf.call(testAL, 'mus'); + expect(actual).toEqual(expected); + }); + it('should find undefined as well (array-like)', function() { + expected = -1; + actual = lastIndexOf.call(testAL, undefined); + expect(actual).not.toEqual(expected); + }); + it('should skip unset indexes (array-like)', function() { + expected = 2; + actual = lastIndexOf.call(testAL, undefined); + expect(actual).toEqual(expected); + }); + it('should use a strict test (array-like)', function() { + actual = lastIndexOf.call(testAL, null); + expect(actual).toEqual(5); + + actual = lastIndexOf.call(testAL, '2'); + expect(actual).toEqual(-1); + }); + it('should skip the first if fromIndex is set', function() { + expect(lastIndexOf.call(testAL, 2, 2)).toEqual(0); + expect(lastIndexOf.call(testAL, 2, 0)).toEqual(0); + expect(lastIndexOf.call(testAL, 2, 6)).toEqual(6); + }); + it('should work with negative fromIndex', function() { + expect(lastIndexOf.call(testAL, 2, -3)).toEqual(6); + expect(lastIndexOf.call(testAL, 2, -9)).toEqual(0); + }); + it('should work with fromIndex being greater than the length', function() { + expect(lastIndexOf.call(testAL, 2, 20)).toEqual(6); + }); + it('should work with fromIndex being negative and greater than the length', function() { + expect(lastIndexOf.call(testAL, 2, -20)).toEqual(-1); + }); + }); + }); + + describe('filter', function() { + var filteredArray, + callback = function callback(o, i, arr) { + return ( + i != 3 && i != 5 + ); + }; + + beforeEach(function() { + testSubject = [2, 3, undefined, true, 'hej', 3, null, false, 0]; + delete testSubject[1]; + filteredArray = [2, undefined, 'hej', null, false, 0]; + }); + describe('Array object', function() { + + it('should call the callback with the proper arguments', function() { + var callback = jasmine.createSpy('callback'), + arr = ['1']; + arr.filter(callback); + expect(callback).toHaveBeenCalledWith('1', 0, arr); + }); + it('should not affect elements added to the array after it has begun', function() { + var arr = [1,2,3], + i = 0; + arr.filter(function(a) { + i++; + if(i <= 4) { + arr.push(a+3); + } + return true; + }); + expect(arr).toEqual([1,2,3,4,5,6]); + expect(i).toBe(3); + }); + it('should skip non-set values', function() { + var passedValues = {}; + testSubject = [1,2,3,4]; + delete testSubject[1]; + testSubject.filter(function(o, i) { + passedValues[i] = o; + return true; + }); + expect(passedValues).toExactlyMatch(testSubject); + }); + it('should pass the right context to the filter', function() { + var passedValues = {}; + testSubject = [1,2,3,4]; + delete testSubject[1]; + testSubject.filter(function(o, i) { + this[i] = o; + return true; + }, passedValues); + expect(passedValues).toExactlyMatch(testSubject); + }); + it('should set the right context when given none', function() { + var context; + [1].filter(function() {context = this;}); + expect(context).toBe(function() {return this}.call()); + }); + it('should remove only the values for which the callback returns false', function() { + var result = testSubject.filter(callback); + expect(result).toExactlyMatch(filteredArray); + }); + it('should leave the original array untouched', function() { + var copy = testSubject.slice(); + testSubject.filter(callback); + expect(testSubject).toExactlyMatch(copy); + }); + it('should not be affected by same-index mutation', function () { + var results = [1, 2, 3] + .filter(function (value, index, array) { + array[index] = 'a'; + return true; + }); + expect(results).toEqual([1, 2, 3]); + }); + }); + describe('Array like', function() { + beforeEach(function() { + testSubject = createArrayLikeFromArray(testSubject); + }); + it('should call the callback with the proper arguments', function() { + var callback = jasmine.createSpy('callback'), + arr = createArrayLikeFromArray(['1']); + Array.prototype.filter.call(arr, callback); + expect(callback).toHaveBeenCalledWith('1', 0, arr); + }); + it('should not affect elements added to the array after it has begun', function() { + var arr = createArrayLikeFromArray([1,2,3]), + i = 0; + Array.prototype.filter.call(arr, function(a) { + i++; + if(i <= 4) { + arr[i+2] = a+3; + } + return true; + }); + delete arr.length; + expect(arr).toExactlyMatch([1,2,3,4,5,6]); + expect(i).toBe(3); + }); + it('should skip non-set values', function() { + var passedValues = {}; + testSubject = createArrayLikeFromArray([1,2,3,4]); + delete testSubject[1]; + Array.prototype.filter.call(testSubject, function(o, i) { + passedValues[i] = o; + return true; + }); + delete testSubject.length; + expect(passedValues).toExactlyMatch(testSubject); + }); + it('should set the right context when given none', function() { + var context; + Array.prototype.filter.call(createArrayLikeFromArray([1]), function() {context = this;}, undefined); + expect(context).toBe(function() {return this}.call()); + }); + it('should pass the right context to the filter', function() { + var passedValues = {}; + testSubject = createArrayLikeFromArray([1,2,3,4]); + delete testSubject[1]; + Array.prototype.filter.call(testSubject, function(o, i) { + this[i] = o; + return true; + }, passedValues); + delete testSubject.length; + expect(passedValues).toExactlyMatch(testSubject); + }); + it('should remove only the values for which the callback returns false', function() { + var result = Array.prototype.filter.call(testSubject, callback); + expect(result).toExactlyMatch(filteredArray); + }); + it('should leave the original array untouched', function() { + var copy = createArrayLikeFromArray(testSubject); + Array.prototype.filter.call(testSubject, callback); + expect(testSubject).toExactlyMatch(copy); + }); + }); + }); + describe('map', function() { + var callback; + beforeEach(function() { + var i = 0; + callback = function() { + return i++; + }; + }); + describe('Array object', function() { + it('should call callback with the right parameters', function() { + var callback = jasmine.createSpy('callback'), + array = [1]; + array.map(callback); + expect(callback).toHaveBeenCalledWith(1, 0, array); + }); + it('should set the context correctly', function() { + var context = {}; + testSubject.map(function(o,i) { + this[i] = o; + }, context); + expect(context).toExactlyMatch(testSubject); + }); + it('should set the right context when given none', function() { + var context; + [1].map(function() {context = this;}); + expect(context).toBe(function() {return this}.call()); + }); + it('should not change the array it is called on', function() { + var copy = testSubject.slice(); + testSubject.map(callback); + expect(testSubject).toExactlyMatch(copy); + }); + it('should only run for the number of objects in the array when it started', function() { + var arr = [1,2,3], + i = 0; + arr.map(function(o) { + arr.push(o+3); + i++; + return o; + }); + expect(arr).toExactlyMatch([1,2,3,4,5,6]); + expect(i).toBe(3); + }); + it('should properly translate the values as according to the callback', function() { + var result = testSubject.map(callback), + expected = [0,0,1,2,3,4,5,6]; + delete expected[1]; + expect(result).toExactlyMatch(expected); + }); + it('should skip non-existing values', function() { + var array = [1,2,3,4], + i = 0; + delete array[2]; + array.map(function() { + i++; + }); + expect(i).toBe(3); + }); + }); + describe('Array-like', function() { + beforeEach(function() { + testSubject = createArrayLikeFromArray(testSubject); + }); + it('should call callback with the right parameters', function() { + var callback = jasmine.createSpy('callback'), + array = createArrayLikeFromArray([1]); + Array.prototype.map.call(array, callback); + expect(callback).toHaveBeenCalledWith(1, 0, array); + }); + it('should set the context correctly', function() { + var context = {}; + Array.prototype.map.call(testSubject, function(o,i) { + this[i] = o; + }, context); + delete testSubject.length; + expect(context).toExactlyMatch(testSubject); + }); + it('should set the right context when given none', function() { + var context; + Array.prototype.map.call(createArrayLikeFromArray([1]), function() {context = this;}); + expect(context).toBe(function() {return this}.call()); + }); + it('should not change the array it is called on', function() { + var copy = createArrayLikeFromArray(testSubject); + Array.prototype.map.call(testSubject, callback); + expect(testSubject).toExactlyMatch(copy); + }); + it('should only run for the number of objects in the array when it started', function() { + var arr = createArrayLikeFromArray([1,2,3]), + i = 0; + Array.prototype.map.call(arr, function(o) { + Array.prototype.push.call(arr, o+3); + i++; + return o; + }); + delete arr.length; + expect(arr).toExactlyMatch([1,2,3,4,5,6]); + expect(i).toBe(3); + }); + it('should properly translate the values as according to the callback', function() { + var result = Array.prototype.map.call(testSubject, callback), + expected = [0,0,1,2,3,4,5,6]; + delete expected[1]; + expect(result).toExactlyMatch(expected); + }); + it('should skip non-existing values', function() { + var array = createArrayLikeFromArray([1,2,3,4]), + i = 0; + delete array[2]; + Array.prototype.map.call(array, function() { + i++; + }); + expect(i).toBe(3); + }); + }); + }); + + describe('reduce', function() { + beforeEach(function() { + testSubject = [1,2,3]; + }); + + describe('Array', function() { + it('should pass the correct arguments to the callback', function() { + var spy = jasmine.createSpy().andReturn(0); + testSubject.reduce(spy); + expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]); + }); + it('should start with the right initialValue', function() { + var spy = jasmine.createSpy().andReturn(0); + testSubject.reduce(spy, 0); + expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]); + }); + it('should not affect elements added to the array after it has begun', function() { + var arr = [1,2,3], + i = 0; + arr.reduce(function(a, b) { + i++; + if(i <= 4) { + arr.push(a+3); + }; + return b; + }); + expect(arr).toEqual([1,2,3,4,5]); + expect(i).toBe(2); + }); + it('should work as expected for empty arrays', function() { + var spy = jasmine.createSpy(); + expect(function() { + [].reduce(spy); + }).toThrow(); + expect(spy).not.toHaveBeenCalled(); + }); + it('should throw correctly if no callback is given', function() { + expect(function() { + testSubject.reduce(); + }).toThrow(); + }); + it('should return the expected result', function() { + expect(testSubject.reduce(function(a,b) { + return (a||'').toString()+(b||'').toString(); + })).toEqual(testSubject.join('')); + }); + it('should not directly affect the passed array', function() { + var copy = testSubject.slice(); + testSubject.reduce(function(a,b) { + return a+b; + }); + expect(testSubject).toEqual(copy); + }); + it('should skip non-set values', function() { + delete testSubject[1]; + var visited = {}; + testSubject.reduce(function(a,b) { + if(a) + visited[a] = true; + if(b) + visited[b] = true; + return 0; + }); + + expect(visited).toEqual({ '1': true, '3': true }); + }); + it('should have the right length', function() { + expect(testSubject.reduce.length).toBe(1); + }); + }); + describe('Array-like objects', function() { + beforeEach(function() { + testSubject = createArrayLikeFromArray(testSubject); + testSubject.reduce = Array.prototype.reduce; + }); + it('should pass the correct arguments to the callback', function() { + var spy = jasmine.createSpy().andReturn(0); + testSubject.reduce(spy); + expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]); + }); + it('should start with the right initialValue', function() { + var spy = jasmine.createSpy().andReturn(0); + testSubject.reduce(spy, 0); + expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]); + }); + it('should not affect elements added to the array after it has begun', function() { + var arr = createArrayLikeFromArray([1,2,3]), + i = 0; + Array.prototype.reduce.call(arr, function(a, b) { + i++; + if(i <= 4) { + arr[i+2] = a+3; + }; + return b; + }); + expect(arr).toEqual({ + 0: 1, + 1: 2, + 2: 3, + 3: 4, + 4: 5, + length: 3 + }); + expect(i).toBe(2); + }); + it('should work as expected for empty arrays', function() { + var spy = jasmine.createSpy(); + expect(function() { + Array.prototype.reduce.call({length: 0}, spy); + }).toThrow(); + expect(spy).not.toHaveBeenCalled(); + }); + it('should throw correctly if no callback is given', function() { + expect(function() { + testSubject.reduce(); + }).toThrow(); + }); + it('should return the expected result', function() { + expect(testSubject.reduce(function(a,b) { + return (a||'').toString()+(b||'').toString(); + })).toEqual('123'); + }); + it('should not directly affect the passed array', function() { + var copy = createArrayLikeFromArray(testSubject); + testSubject.reduce(function(a,b) { + return a+b; + }); + delete(testSubject.reduce); + expect(testSubject).toEqual(copy); + }); + it('should skip non-set values', function() { + delete testSubject[1]; + var visited = {}; + testSubject.reduce(function(a,b) { + if(a) + visited[a] = true; + if(b) + visited[b] = true; + return 0; + }); + + expect(visited).toEqual({ '1': true, '3': true }); + }); + it('should have the right length', function() { + expect(testSubject.reduce.length).toBe(1); + }); + }); + }); + describe('reduceRight', function() { + beforeEach(function() { + testSubject = [1,2,3]; + }); + + describe('Array', function() { + it('should pass the correct arguments to the callback', function() { + var spy = jasmine.createSpy().andReturn(0); + testSubject.reduceRight(spy); + expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]); + }); + it('should start with the right initialValue', function() { + var spy = jasmine.createSpy().andReturn(0); + testSubject.reduceRight(spy, 0); + expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]); + }); + it('should not affect elements added to the array after it has begun', function() { + var arr = [1,2,3], + i = 0; + arr.reduceRight(function(a, b) { + i++; + if(i <= 4) { + arr.push(a+3); + }; + return b; + }); + expect(arr).toEqual([1,2,3,6,5]); + expect(i).toBe(2); + }); + it('should work as expected for empty arrays', function() { + var spy = jasmine.createSpy(); + expect(function() { + [].reduceRight(spy); + }).toThrow(); + expect(spy).not.toHaveBeenCalled(); + }); + it('should work as expected for empty arrays with an initial value', function() { + var spy = jasmine.createSpy(), + result; + + result = [].reduceRight(spy, ''); + expect(spy).not.toHaveBeenCalled(); + expect(result).toBe(''); + }); + it('should throw correctly if no callback is given', function() { + expect(function() { + testSubject.reduceRight(); + }).toThrow(); + }); + it('should return the expected result', function() { + expect(testSubject.reduceRight(function(a,b) { + return (a||'').toString()+(b||'').toString(); + })).toEqual('321'); + }); + it('should not directly affect the passed array', function() { + var copy = testSubject.slice(); + testSubject.reduceRight(function(a,b) { + return a+b; + }); + expect(testSubject).toEqual(copy); + }); + it('should skip non-set values', function() { + delete testSubject[1]; + var visited = {}; + testSubject.reduceRight(function(a,b) { + if(a) + visited[a] = true; + if(b) + visited[b] = true; + return 0; + }); + + expect(visited).toEqual({ '1': true, '3': true }); + }); + it('should have the right length', function() { + expect(testSubject.reduceRight.length).toBe(1); + }); + }); + describe('Array-like objects', function() { + beforeEach(function() { + testSubject = createArrayLikeFromArray(testSubject); + testSubject.reduceRight = Array.prototype.reduceRight; + }); + it('should pass the correct arguments to the callback', function() { + var spy = jasmine.createSpy().andReturn(0); + testSubject.reduceRight(spy); + expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]); + }); + it('should start with the right initialValue', function() { + var spy = jasmine.createSpy().andReturn(0); + testSubject.reduceRight(spy, 0); + expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]); + }); + it('should not affect elements added to the array after it has begun', function() { + var arr = createArrayLikeFromArray([1,2,3]), + i = 0; + Array.prototype.reduceRight.call(arr, function(a, b) { + i++; + if(i <= 4) { + arr[i+2] = a+3; + }; + return b; + }); + expect(arr).toEqual({ + 0: 1, + 1: 2, + 2: 3, + 3: 6, + 4: 5, + length: 3 // does not get updated on property assignment + }); + expect(i).toBe(2); + }); + it('should work as expected for empty arrays', function() { + var spy = jasmine.createSpy(); + expect(function() { + Array.prototype.reduceRight.call({length:0}, spy); + }).toThrow(); + expect(spy).not.toHaveBeenCalled(); + }); + it('should throw correctly if no callback is given', function() { + expect(function() { + testSubject.reduceRight(); + }).toThrow(); + }); + it('should return the expected result', function() { + expect(testSubject.reduceRight(function(a,b) { + return (a||'').toString()+(b||'').toString(); + })).toEqual('321'); + }); + it('should not directly affect the passed array', function() { + var copy = createArrayLikeFromArray(testSubject); + testSubject.reduceRight(function(a,b) { + return a+b; + }); + delete(testSubject.reduceRight); + expect(testSubject).toEqual(copy); + }); + it('should skip non-set values', function() { + delete testSubject[1]; + var visited = {}; + testSubject.reduceRight(function(a,b) { + if(a) + visited[a] = true; + if(b) + visited[b] = true; + return 0; + }); + + expect(visited).toEqual({ '1': true, '3': true }); + }); + it('should have the right length', function() { + expect(testSubject.reduceRight.length).toBe(1); + }); + }); + }); + + describe('isArray', function () { + it('should work for Array', function () { + var ret = Array.isArray([]); + + expect(ret).toBe(true); + }); + + it('should fail for other objects', function () { + var objects = [ + "someString", + true, + false, + 42, + 0, + {}, + Object.create && Object.create(null) || null, + /foo/, + arguments, + document.getElementsByTagName("div") + ]; + + objects.forEach(function (v) { + expect(Array.isArray(v)).toBe(false); + }); + }); + }); + + describe('unshift', function () { + it('should return length', function () { + expect([].unshift(0)).toEqual(1); + }); + }); + + describe('splice', function () { + var b = ["b"], + a = [1, "a", b], + test; + + var makeArray = function(l, prefix) { + prefix = prefix || ""; + var a = []; + while (l--) { + a.unshift(prefix + Array(l + 1).join(" ") + l) + } + return a + }; + + beforeEach(function() { + test = a.slice(0); + }); + + it('basic implementation test 1', function () { + expect(test.splice(0)).toEqual(a); + }); + it('basic implementation test 2', function () { + test.splice(0, 2); + expect(test).toEqual([b]); + }); + + it('should return right result 1', function () { + expect((function() { + var array = []; + + array.splice(0, 0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20); + array.splice(1, 0, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21","F22", "F23", "F24", "F25", "F26"); + array.splice(5, 0, "XXX"); + + return array.join("|"); + }())).toBe("1|F1|F2|F3|F4|XXX|F5|F6|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20"); + }); + + it('should return right result 2', function () { + expect((function() { + var array = makeArray(6); + + array.splice(array.length - 1, 1, ""); + array.splice(0, 1, 1,2,3,4); + array.splice(0, 0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, 21, 22, 23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45); + + array.splice(4, 0, "99999999999999"); + return array.join("|"); + }())).toBe("1|2|3|4|99999999999999|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|1|2|3|4| 1| 2| 3| 4|"); + }); + + it('should return right result 3', function () { + expect((function() { + var array = [1,2,3]; + + array.splice(0); + array.splice(0, 1, 1,2,3,4,5,6,7,8,9,10); + array.splice(1, 1, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21","F22", "F23", "F24", "F25", "F26"); + array.splice(5, 1, "YYY", "XXX"); + array.splice(0, 1); + array.splice(0, 2); + array.pop(); + array.push.apply(array, makeArray(10, "-")); + array.splice(array.length - 2, 10); + array.splice(); + array.splice(1, 1, 1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9); + array.splice(1, 1, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21","F22", "F23", "F24", "F25", "F26",1,23,4,5,6,7,8); + array.splice(30, 10); + array.splice(30, 1); + array.splice(30, 0); + array.splice(2, 5, 1,2,3,"P", "LLL", "CCC", "YYY", "XXX"); + array.push(1,2,3,4,5,6); + array.splice(1, 6, 1,2,3,4,5,6,7,8,9,4,5,6,7,8,9); + array.splice(3, 7); + array.unshift(7,8,9,10,11); + array.pop(); + array.splice(5, 2); + array.pop(); + array.unshift.apply(array, makeArray(8, "~")); + array.pop(); + array.splice(3, 1, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21","F22", "F23", "F24", "F25", "F26",1,23,4,5,6,7,8); + array.splice(4, 5, "P", "LLL", "CCC", "YYY", "XXX"); + + return array.join("|"); + }())).toBe("~0|~ 1|~ 2|F1|P|LLL|CCC|YYY|XXX|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|1|23|4|5|6|7|8|~ 4|~ 5|~ 6|~ 7|7|8|9|10|11|2|4|5|6|7|8|9|CCC|YYY|XXX|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|1|23|4|9|10|1|2|3|4|5|6|7|8|9|YYY|XXX|F6|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|3|4|5|6|7|8|9|-0|- 1|- 2|- 3|- 4|- 5|- 6|- 7|1|2|3"); + }); + + + it('should do nothing if method called with no arguments', function () { + expect(test.splice()).toEqual([]); + expect(test).toEqual(a); + }); + //TODO:: Is this realy TRUE behavior? + it('should set first argument to 0 if first argument is set but undefined', function () { + var test2 = test.slice(0); + expect(test.splice(void 0, 2)).toEqual(test2.splice(0, 2)); + expect(test).toEqual(test2); + }); + + it('should deleted and return all items after "start" when second argument is undefined', function () { + expect(test.splice(0)).toEqual(a); + expect(test).toEqual([]); + }); + it('should deleted and return all items after "start" when second argument is undefined', function () { + expect(test.splice(2)).toEqual([b]); + expect(test).toEqual([1, "a"]); + }); + it('runshould have the right length', function () { + expect(test.splice.length).toBe(2); + }); + }); + + +}); diff --git a/dist/bower_components/es5-shim/tests/spec/s-date.js b/dist/bower_components/es5-shim/tests/spec/s-date.js new file mode 100644 index 000000000..a2e288c6f --- /dev/null +++ b/dist/bower_components/es5-shim/tests/spec/s-date.js @@ -0,0 +1,152 @@ +describe('Date', function () { + + describe('now', function () { + it('should be the current time', function () { + expect(Date.now() === new Date().getTime()).toBe(true); + }); + }); + + describe("parse", function () { + // TODO: Write the rest of the test. + + it('should support extended years', function () { + + expect(Date.parse('0001-01-01T00:00:00Z')).toBe(-62135596800000); + expect(Date.parse('+275760-09-13T00:00:00.000Z')).toBe(8.64e15); + expect(Date.parse('+033658-09-27T01:46:40.000Z')).toBe(1e15); + expect(Date.parse('-000001-01-01T00:00:00Z')).toBe(-62198755200000); + expect(Date.parse('+002009-12-15T00:00:00Z')).toBe(1260835200000); + + }); + + it('should work', function () { + //Chrome 19 Opera 12 Firefox 11 IE 9 Safari 5.1.1 + expect(Date.parse("2012-11-31T23:59:59.000Z")).toBeFalsy(); //1354406399000 NaN NaN 1354406399000 NaN + expect(Date.parse("2012-12-31T23:59:59.000Z")).toBe(1356998399000); //1356998399000 1356998399000 1356998399000 1356998399000 1356998399000 + expect(Date.parse("2012-12-31T23:59:60.000Z")).toBeFalsy(); //NaN NaN NaN NaN 1356998400000 + expect(Date.parse("2012-04-04T05:02:02.170Z")).toBe(1333515722170); //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 + expect(Date.parse("2012-04-04T05:02:02.170999Z")).toBe(1333515722170); //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 + expect(Date.parse("2012-04-04T05:02:02.17Z")).toBe(1333515722170); //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 + expect(Date.parse("2012-04-04T05:02:02.1Z")).toBe(1333515722100); //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 + expect(Date.parse("2012-04-04T24:00:00.000Z")).toBe(1333584000000); //NaN 1333584000000 1333584000000 1333584000000 1333584000000 + expect(Date.parse("2012-04-04T24:00:00.500Z")).toBeFalsy(); //NaN NaN 1333584000500 1333584000500 NaN + expect(Date.parse("2012-12-31T10:08:60.000Z")).toBeFalsy(); //NaN NaN NaN NaN 1356948540000 + expect(Date.parse("2012-13-01T12:00:00.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN + expect(Date.parse("2012-12-32T12:00:00.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN + expect(Date.parse("2012-12-31T25:00:00.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN + expect(Date.parse("2012-12-31T24:01:00.000Z")).toBeFalsy(); //NaN NaN NaN 1356998460000 NaN + expect(Date.parse("2012-12-31T12:60:00.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN + expect(Date.parse("2012-12-31T12:00:60.000Z")).toBeFalsy(); //NaN NaN NaN NaN 1356955260000 + expect(Date.parse("2012-00-31T23:59:59.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN + expect(Date.parse("2012-12-00T23:59:59.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN + expect(Date.parse("2012-02-29T12:00:00.000Z")).toBe(1330516800000); //1330516800000 1330516800000 1330516800000 1330516800000 1330516800000 + expect(Date.parse("2011-02-29T12:00:00.000Z")).toBeFalsy(); //1298980800000 NaN NaN 1298980800000 NaN + expect(Date.parse("2011-03-01T12:00:00.000Z")).toBe(1298980800000); //1298980800000 1298980800000 1298980800000 1298980800000 1298980800000 + + // extended years: + expect(Date.parse("0000-01-01T00:00:00.000Z")).toBe(-621672192e5); //-621672192e5 -621672192e5 -621672192e5 -621672192e5 -621672192e5 + expect(Date.parse("+275760-09-13T00:00:00.000Z")).toBe(8.64e15); //8.64e15 NaN 8.64e15 8.64e15 8.64e15 + expect(Date.parse("-271821-04-20T00:00:00.000Z")).toBe(-8.64e15); //-8.64e15 NaN -8.64e15 -8.64e15 -8.6400000864e15 + expect(Date.parse("+275760-09-13T00:00:00.001Z")).toBeFalsy(); //NaN NaN NaN 8.64e15 + 1 8.64e15 + 1 + expect(Date.parse("-271821-04-19T23:59:59.999Z")).toBeFalsy(); //NaN NaN NaN -8.64e15 - 1 -8.6400000864e15 - 1 + + // https://github.com/kriskowal/es5-shim/issues/80 Safari bug with leap day + expect(Date.parse("2034-03-01T00:00:00.000Z") - + Date.parse("2034-02-27T23:59:59.999Z")).toBe(86400001); //86400001 86400001 86400001 86400001 1 + + // Time Zone Offset + expect(Date.parse("2012-01-29T12:00:00.000+01:00")).toBe(132783480e4);//132783480e4 132783480e4 132783480e4 132783480e4 132783480e4 + expect(Date.parse("2012-01-29T12:00:00.000-00:00")).toBe(132783840e4);//132783840e4 132783840e4 132783840e4 132783840e4 132783840e4 + expect(Date.parse("2012-01-29T12:00:00.000+00:00")).toBe(132783840e4);//132783840e4 132783840e4 132783840e4 132783840e4 132783840e4 + expect(Date.parse("2012-01-29T12:00:00.000+23:59")).toBe(132775206e4);//132775206e4 132775206e4 132775206e4 132775206e4 132775206e4 + expect(Date.parse("2012-01-29T12:00:00.000-23:59")).toBe(132792474e4);//132792474e4 132792474e4 132792474e4 132792474e4 132792474e4 + expect(Date.parse("2012-01-29T12:00:00.000+24:00")).toBeFalsy(); //NaN 1327752e6 NaN 1327752000000 1327752000000 + expect(Date.parse("2012-01-29T12:00:00.000+24:01")).toBeFalsy(); //NaN NaN NaN 1327751940000 1327751940000 + expect(Date.parse("2012-01-29T12:00:00.000+24:59")).toBeFalsy(); //NaN NaN NaN 1327748460000 1327748460000 + expect(Date.parse("2012-01-29T12:00:00.000+25:00")).toBeFalsy(); //NaN NaN NaN NaN NaN + expect(Date.parse("2012-01-29T12:00:00.000+00:60")).toBeFalsy(); //NaN NaN NaN NaN NaN + expect(Date.parse("-271821-04-20T00:00:00.000+00:01")).toBeFalsy(); //NaN NaN NaN -864000000006e4 -864000008646e4 + expect(Date.parse("-271821-04-20T00:01:00.000+00:01")).toBe(-8.64e15);//-8.64e15 NaN -8.64e15 -8.64e15 -864000008640e4 + + // When time zone is missed, local offset should be used (ES 5.1 bug) + // see https://bugs.ecmascript.org/show_bug.cgi?id=112 + var tzOffset = Number(new Date(1970, 0)); + // same as (new Date().getTimezoneOffset() * 60000) + expect(Date.parse('1970-01-01T00:00:00')).toBe(tzOffset); //tzOffset 0 0 0 NaN + }); + + it("should be able to coerce to a number", function(){ + var actual = Number(new Date(1970, 0)); + var expected = parseInt(actual, 10); + expect(actual).toBeDefined(); + expect(actual).toEqual(expected); + expect(isNaN(actual)).toBeFalsy(); + }); + + }); + + describe("toString", function(){ + var actual = (new Date(1970, 0)).toString(); + beforeEach(function(){ + actual = (new Date(1970, 0)).toString(); + }); + it("should show correct date info for "+actual, function(){ + expect(actual).toMatch(/1970/); + expect(actual).toMatch(/jan/i); + expect(actual).toMatch(/thu/i); + expect(actual).toMatch(/00:00:00/); + }); + }); + + describe("valueOf", function(){ + var actual = (new Date(1970, 0)); + beforeEach(function(){ + actual = (new Date(1970, 0)).valueOf(); + }); + it("should give an int value", function(){ + expect(parseInt(actual, 10)).toBeTruthy(); + }); + }); + + describe("toISOString", function () { + // TODO: write the rest of the test. + + it('should support extended years', function () { + expect(new Date(-62198755200000).toISOString().indexOf('-000001-01-01')).toBe(0); + expect(new Date(8.64e15).toISOString().indexOf('+275760-09-13')).toBe(0); + }); + + it('should return correct dates', function () { + expect(new Date(-1).toISOString()).toBe('1969-12-31T23:59:59.999Z');// Safari 5.1.5 "1969-12-31T23:59:59.-01Z" + expect(new Date(-3509827334573292).toISOString()).toBe('-109252-01-01T10:37:06.708Z'); // Opera 11.61/Opera 12 bug with Date#getUTCMonth + }); + + }); + + describe("toJSON", function () { + + // Opera 11.6x/12 bug + it('should call toISOString', function () { + var date = new Date(0); + date.toISOString = function () { + return 1; + }; + expect(date.toJSON()).toBe(1); + }); + + it('should return null for not finite dates', function () { + var date = new Date(NaN), + json; + try { + json = date.toJSON(); + } catch (e) {} + expect(json).toBe(null); + }); + + it('should return the isoString when stringified', function () { + var date = new Date(); + expect(JSON.stringify(date.toISOString())).toBe(JSON.stringify(date)); + }) + }); + +}); \ No newline at end of file diff --git a/dist/bower_components/es5-shim/tests/spec/s-function.js b/dist/bower_components/es5-shim/tests/spec/s-function.js new file mode 100644 index 000000000..aa4361e7d --- /dev/null +++ b/dist/bower_components/es5-shim/tests/spec/s-function.js @@ -0,0 +1,147 @@ + +describe('Function', function() { + "use strict"; + describe('bind', function() { + var actual, expected, + testSubject; + + testSubject = { + push: function(o) { + this.a.push(o); + } + }; + + function func() { + Array.prototype.forEach.call(arguments, function(a) { + this.push(a); + }, this); + return this; + }; + + beforeEach(function() { + actual = []; + testSubject.a = []; + }); + + it('binds properly without a context', function() { + var context; + testSubject.func = function() { + context = this; + }.bind(); + testSubject.func(); + expect(context).toBe(function() {return this}.call()); + }); + it('binds properly without a context, and still supplies bound arguments', function() { + var a, context; + testSubject.func = function() { + a = Array.prototype.slice.call(arguments); + context = this; + }.bind(undefined, 1,2,3); + testSubject.func(1,2,3); + expect(a).toEqual([1,2,3,1,2,3]); + expect(context).toBe(function() {return this}.call()); + }); + it('binds a context properly', function() { + testSubject.func = func.bind(actual); + testSubject.func(1,2,3); + expect(actual).toEqual([1,2,3]); + expect(testSubject.a).toEqual([]); + }); + it('binds a context and supplies bound arguments', function() { + testSubject.func = func.bind(actual, 1,2,3); + testSubject.func(4,5,6); + expect(actual).toEqual([1,2,3,4,5,6]); + expect(testSubject.a).toEqual([]); + }); + + it('returns properly without binding a context', function() { + testSubject.func = function() { + return this; + }.bind(); + var context = testSubject.func(); + expect(context).toBe(function() {return this}.call()); + }); + it('returns properly without binding a context, and still supplies bound arguments', function() { + var context; + testSubject.func = function() { + context = this; + return Array.prototype.slice.call(arguments); + }.bind(undefined, 1,2,3); + actual = testSubject.func(1,2,3); + expect(context).toBe(function() {return this}.call()); + expect(actual).toEqual([1,2,3,1,2,3]); + }); + it('returns properly while binding a context properly', function() { + var ret; + testSubject.func = func.bind(actual); + ret = testSubject.func(1,2,3); + expect(ret).toBe(actual); + expect(ret).not.toBe(testSubject); + }); + it('returns properly while binding a context and supplies bound arguments', function() { + var ret; + testSubject.func = func.bind(actual, 1,2,3); + ret = testSubject.func(4,5,6); + expect(ret).toBe(actual); + expect(ret).not.toBe(testSubject); + }); + it('passes the correct arguments as a constructor', function() { + var ret, expected = { name: "Correct" }; + testSubject.func = function(arg) { + return arg; + }.bind({ name: "Incorrect" }); + ret = new testSubject.func(expected); + expect(ret).toBe(expected); + }); + it('returns the return value of the bound function when called as a constructor', function () { + var oracle = [1, 2, 3]; + var subject = function () { + return oracle; + }.bind(null); + var result = new subject; + expect(result).toBe(oracle); + }); + it('returns the correct value if constructor returns primitive', function() { + var oracle = [1, 2, 3]; + var subject = function () { + return oracle; + }.bind(null); + var result = new subject; + expect(result).toBe(oracle); + + oracle = {}; + result = new subject; + expect(result).toBe(oracle); + + oracle = function(){}; + result = new subject; + expect(result).toBe(oracle); + + oracle = "asdf"; + result = new subject; + expect(result).not.toBe(oracle); + + oracle = null; + result = new subject; + expect(result).not.toBe(oracle); + + oracle = true; + result = new subject; + expect(result).not.toBe(oracle); + + oracle = 1; + result = new subject; + expect(result).not.toBe(oracle); + }); + it('returns the value that instance of original "class" when called as a constructor', function() { + var classA = function(x) { + this.name = x || "A"; + } + var classB = classA.bind(null, "B"); + + var result = new classB; + expect(result instanceof classA).toBe(true); + expect(result instanceof classB).toBe(true); + }); + }); +}); diff --git a/dist/bower_components/es5-shim/tests/spec/s-number.js b/dist/bower_components/es5-shim/tests/spec/s-number.js new file mode 100644 index 000000000..b09ae2b92 --- /dev/null +++ b/dist/bower_components/es5-shim/tests/spec/s-number.js @@ -0,0 +1,14 @@ +describe('Number', function () { + 'use strict'; + + describe('toFixed', function () { + it('should convert numbers correctly', function () { + expect((0.00008).toFixed(3)).toBe('0.000'); + expect((0.9).toFixed(0)).toBe('1'); + expect((1.255).toFixed(2)).toBe('1.25'); + expect((1843654265.0774949).toFixed(5)).toBe('1843654265.07749'); + expect((1000000000000000128).toFixed(0)).toBe('1000000000000000128'); + }); + }); + +}); diff --git a/dist/bower_components/es5-shim/tests/spec/s-object.js b/dist/bower_components/es5-shim/tests/spec/s-object.js new file mode 100644 index 000000000..4c540bf9b --- /dev/null +++ b/dist/bower_components/es5-shim/tests/spec/s-object.js @@ -0,0 +1,181 @@ +describe('Object', function () { + "use strict"; + + describe("Object.keys", function () { + var obj = { + "str": "boz", + "obj": { }, + "arr": [], + "bool": true, + "num": 42, + "null": null, + "undefined": undefined + }; + + var loopedValues = []; + for (var k in obj) { + loopedValues.push(k); + } + + var keys = Object.keys(obj); + it('should have correct length', function () { + expect(keys.length).toBe(7); + }); + + it('should return an Array', function () { + expect(Array.isArray(keys)).toBe(true); + }); + + it('should return names which are own properties', function () { + keys.forEach(function (name) { + expect(obj.hasOwnProperty(name)).toBe(true); + }); + }); + + it('should return names which are enumerable', function () { + keys.forEach(function (name) { + expect(loopedValues.indexOf(name)).toNotBe(-1); + }) + }); + + it('should throw error for non object', function () { + var e = {}; + expect(function () { + try { + Object.keys(42) + } catch (err) { + throw e; + } + }).toThrow(e); + }); + }); + + describe("Object.isExtensible", function () { + var obj = { }; + + it('should return true if object is extensible', function () { + expect(Object.isExtensible(obj)).toBe(true); + }); + + it('should return false if object is not extensible', function () { + expect(Object.isExtensible(Object.preventExtensions(obj))).toBe(false); + }); + + it('should return false if object is seal', function () { + expect(Object.isExtensible(Object.seal(obj))).toBe(false); + }); + + it('should return false if object is freeze', function () { + expect(Object.isExtensible(Object.freeze(obj))).toBe(false); + }); + + it('should throw error for non object', function () { + var e1 = {}; + expect(function () { + try { + Object.isExtensible(42) + } catch (err) { + throw e1; + } + }).toThrow(e1); + }); + }); + + describe("Object.defineProperty", function () { + var obj; + + beforeEach(function() { + obj = {}; + + Object.defineProperty(obj, 'name', { + value : 'Testing', + configurable: true, + enumerable: true, + writable: true + }); + }); + + it('should return the initial value', function () { + expect(obj.hasOwnProperty('name')).toBeTruthy(); + expect(obj.name).toBe('Testing'); + }); + + it('should be setable', function () { + obj.name = 'Other'; + expect(obj.name).toBe('Other'); + }); + + it('should return the parent initial value', function () { + var child = Object.create(obj, {}); + + expect(child.name).toBe('Testing'); + expect(child.hasOwnProperty('name')).toBeFalsy(); + }); + + it('should not override the parent value', function () { + var child = Object.create(obj, {}); + + Object.defineProperty(child, 'name', { + value : 'Other' + }); + + expect(obj.name).toBe('Testing'); + expect(child.name).toBe('Other'); + }); + + it('should throw error for non object', function () { + expect(function () { + Object.defineProperty(42, 'name', {}); + }).toThrow(); + }); + }); + + describe("Object.getOwnPropertyDescriptor", function () { + it('should return undefined because the object does not own the property', function () { + var descr = Object.getOwnPropertyDescriptor({}, 'name'); + + expect(descr).toBeUndefined() + }); + + it('should return a data descriptor', function () { + var descr = Object.getOwnPropertyDescriptor({name: 'Testing'}, 'name'); + + expect(descr).not.toBeUndefined(); + expect(descr.value).toBe('Testing'); + expect(descr.writable).toBe(true); + expect(descr.enumerable).toBe(true); + expect(descr.configurable).toBe(true); + }); + + it('should return undefined because the object does not own the property', function () { + var descr = Object.getOwnPropertyDescriptor(Object.create({name: 'Testing'}, {}), 'name'); + + expect(descr).toBeUndefined() + }); + + it('should return a data descriptor', function () { + var obj = Object.create({}, { + name: { + value : 'Testing', + configurable: true, + enumerable: true, + writable: true + } + }); + + var descr = Object.getOwnPropertyDescriptor(obj, 'name'); + + expect(descr).not.toBeUndefined(); + expect(descr.value).toBe('Testing'); + expect(descr.writable).toBe(true); + expect(descr.enumerable).toBe(true); + expect(descr.configurable).toBe(true); + }); + + it('should throw error for non object', function () { + expect(function () { + Object.getOwnPropertyDescriptor(42, 'name'); + }).toThrow(); + }); + }); +}); diff --git a/dist/bower_components/es5-shim/tests/spec/s-string.js b/dist/bower_components/es5-shim/tests/spec/s-string.js new file mode 100644 index 000000000..9b6910d7e --- /dev/null +++ b/dist/bower_components/es5-shim/tests/spec/s-string.js @@ -0,0 +1,204 @@ +describe('String', function() { + "use strict"; + describe("trim", function() { + var test = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFFHello, World!\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF"; + + it('trims all ES5 whitespace', function() { + expect(test.trim()).toEqual("Hello, World!"); + expect(test.trim().length).toEqual(13); + }); + }); + + describe("split", function() { + var test = "ab"; + + it('If "separator" is undefined must return Array with one String - "this" string', function() { + expect(test.split()).toEqual([test]); + expect(test.split(void 0)).toEqual([test]); + }); + + it('If "separator" is undefined and "limit" set to 0 must return Array[]', function() { + expect(test.split(void 0, 0)).toEqual([]); + }); + + describe('Tests from Steven Levithan', function () { + it("''.split() results in ['']", function () { + expect(''.split()).toEqual(['']); + }); + it("''.split(/./) results in ['']", function () { + expect(''.split(/./)).toEqual(['']); + }); + it("''.split(/.?/) results in []", function () { + expect(''.split(/.?/)).toEqual([]); + }); + it("''.split(/.??/) results in []", function () { + expect(''.split(/.??/)).toEqual([]); + }); + it("'ab'.split(/a*/) results in ['', 'b']", function () { + expect('ab'.split(/a*/)).toEqual(['', 'b']); + }); + it("'ab'.split(/a*?/) results in ['a', 'b']", function () { + expect('ab'.split(/a*?/)).toEqual(['a', 'b']); + }); + it("'ab'.split(/(?:ab)/) results in ['', '']", function () { + expect('ab'.split(/(?:ab)/)).toEqual(['', '']); + }); + it("'ab'.split(/(?:ab)*/) results in ['', '']", function () { + expect('ab'.split(/(?:ab)*/)).toEqual(['', '']); + }); + it("'ab'.split(/(?:ab)*?/) results in ['a', 'b']", function () { + expect('ab'.split(/(?:ab)*?/)).toEqual(['a', 'b']); + }); + it("'test'.split('') results in ['t', 'e', 's', 't']", function () { + expect('test'.split('')).toEqual(['t', 'e', 's', 't']); + }); + it("'test'.split() results in ['test']", function () { + expect('test'.split()).toEqual(['test']); + }); + it("'111'.split(1) results in ['', '', '', '']", function () { + expect('111'.split(1)).toEqual(['', '', '', '']); + }); + it("'test'.split(/(?:)/, 2) results in ['t', 'e']", function () { + expect('test'.split(/(?:)/, 2)).toEqual(['t', 'e']); + }); + it("'test'.split(/(?:)/, -1) results in ['t', 'e', 's', 't']", function () { + expect('test'.split(/(?:)/, -1)).toEqual(['t', 'e', 's', 't']); + }); + it("'test'.split(/(?:)/, undefined) results in ['t', 'e', 's', 't']", function () { + expect('test'.split(/(?:)/, undefined)).toEqual(['t', 'e', 's', 't']); + }); + it("'test'.split(/(?:)/, null) results in []", function () { + expect('test'.split(/(?:)/, null)).toEqual([]); + }); + it("'test'.split(/(?:)/, NaN) results in []", function () { + expect('test'.split(/(?:)/, NaN)).toEqual([]); + }); + it("'test'.split(/(?:)/, true) results in ['t']", function () { + expect('test'.split(/(?:)/, true)).toEqual(['t']); + }); + it("'test'.split(/(?:)/, '2') results in ['t', 'e']", function () { + expect('test'.split(/(?:)/, '2')).toEqual(['t', 'e']); + }); + it("'test'.split(/(?:)/, 'two') results in []", function () { + expect('test'.split(/(?:)/, 'two')).toEqual([]); + }); + it("'a'.split(/-/) results in ['a']", function () { + expect('a'.split(/-/)).toEqual(['a']); + }); + it("'a'.split(/-?/) results in ['a']", function () { + expect('a'.split(/-?/)).toEqual(['a']); + }); + it("'a'.split(/-??/) results in ['a']", function () { + expect('a'.split(/-??/)).toEqual(['a']); + }); + it("'a'.split(/a/) results in ['', '']", function () { + expect('a'.split(/a/)).toEqual(['', '']); + }); + it("'a'.split(/a?/) results in ['', '']", function () { + expect('a'.split(/a?/)).toEqual(['', '']); + }); + it("'a'.split(/a??/) results in ['a']", function () { + expect('a'.split(/a??/)).toEqual(['a']); + }); + it("'ab'.split(/-/) results in ['ab']", function () { + expect('ab'.split(/-/)).toEqual(['ab']); + }); + it("'ab'.split(/-?/) results in ['a', 'b']", function () { + expect('ab'.split(/-?/)).toEqual(['a', 'b']); + }); + it("'ab'.split(/-??/) results in ['a', 'b']", function () { + expect('ab'.split(/-??/)).toEqual(['a', 'b']); + }); + it("'a-b'.split(/-/) results in ['a', 'b']", function () { + expect('a-b'.split(/-/)).toEqual(['a', 'b']); + }); + it("'a-b'.split(/-?/) results in ['a', 'b']", function () { + expect('a-b'.split(/-?/)).toEqual(['a', 'b']); + }); + it("'a-b'.split(/-??/) results in ['a', '-', 'b']", function () { + expect('a-b'.split(/-??/)).toEqual(['a', '-', 'b']); + }); + it("'a--b'.split(/-/) results in ['a', '', 'b']", function () { + expect('a--b'.split(/-/)).toEqual(['a', '', 'b']); + }); + it("'a--b'.split(/-?/) results in ['a', '', 'b']", function () { + expect('a--b'.split(/-?/)).toEqual(['a', '', 'b']); + }); + it("'a--b'.split(/-??/) results in ['a', '-', '-', 'b']", function () { + expect('a--b'.split(/-??/)).toEqual(['a', '-', '-', 'b']); + }); + it("''.split(/()()/) results in []", function () { + expect(''.split(/()()/)).toEqual([]); + }); + it("'.'.split(/()()/) results in ['.']", function () { + expect('.'.split(/()()/)).toEqual(['.']); + }); + it("'.'.split(/(.?)(.?)/) results in ['', '.', '', '']", function () { + expect('.'.split(/(.?)(.?)/)).toEqual(['', '.', '', '']); + }); + it("'.'.split(/(.??)(.??)/) results in ['.']", function () { + expect('.'.split(/(.??)(.??)/)).toEqual(['.']); + }); + it("'.'.split(/(.)?(.)?/) results in ['', '.', undefined, '']", function () { + expect('.'.split(/(.)?(.)?/)).toEqual(['', '.', undefined, '']); + }); + it("'Aboldandcoded'.split(/<(\\/)?([^<>]+)>/) results in ['A', undefined, 'B', 'bold', '/', 'B', 'and', undefined, 'CODE', 'coded', '/', 'CODE', '']", function () { + expect('Aboldandcoded'.split(/<(\/)?([^<>]+)>/)).toEqual(['A', undefined, 'B', 'bold', '/', 'B', 'and', undefined, 'CODE', 'coded', '/', 'CODE', '']); + }); + it("'tesst'.split(/(s)*/) results in ['t', undefined, 'e', 's', 't']", function () { + expect('tesst'.split(/(s)*/)).toEqual(['t', undefined, 'e', 's', 't']); + }); + it("'tesst'.split(/(s)*?/) results in ['t', undefined, 'e', undefined, 's', undefined, 's', undefined, 't']", function () { + expect('tesst'.split(/(s)*?/)).toEqual(['t', undefined, 'e', undefined, 's', undefined, 's', undefined, 't']); + }); + it("'tesst'.split(/(s*)/) results in ['t', '', 'e', 'ss', 't']", function () { + expect('tesst'.split(/(s*)/)).toEqual(['t', '', 'e', 'ss', 't']); + }); + it("'tesst'.split(/(s*?)/) results in ['t', '', 'e', '', 's', '', 's', '', 't']", function () { + expect('tesst'.split(/(s*?)/)).toEqual(['t', '', 'e', '', 's', '', 's', '', 't']); + }); + it("'tesst'.split(/(?:s)*/) results in ['t', 'e', 't']", function () { + expect('tesst'.split(/(?:s)*/)).toEqual(['t', 'e', 't']); + }); + it("'tesst'.split(/(?=s+)/) results in ['te', 's', 'st']", function () { + expect('tesst'.split(/(?=s+)/)).toEqual(['te', 's', 'st']); + }); + it("'test'.split('t') results in ['', 'es', '']", function () { + expect('test'.split('t')).toEqual(['', 'es', '']); + }); + it("'test'.split('es') results in ['t', 't']", function () { + expect('test'.split('es')).toEqual(['t', 't']); + }); + it("'test'.split(/t/) results in ['', 'es', '']", function () { + expect('test'.split(/t/)).toEqual(['', 'es', '']); + }); + it("'test'.split(/es/) results in ['t', 't']", function () { + expect('test'.split(/es/)).toEqual(['t', 't']); + }); + it("'test'.split(/(t)/) results in ['', 't', 'es', 't', '']", function () { + expect('test'.split(/(t)/)).toEqual(['', 't', 'es', 't', '']); + }); + it("'test'.split(/(es)/) results in ['t', 'es', 't']", function () { + expect('test'.split(/(es)/)).toEqual(['t', 'es', 't']); + }); + it("'test'.split(/(t)(e)(s)(t)/) results in ['', 't', 'e', 's', 't', '']", function () { + expect('test'.split(/(t)(e)(s)(t)/)).toEqual(['', 't', 'e', 's', 't', '']); + }); + it("'.'.split(/(((.((.??)))))/) results in ['', '.', '.', '.', '', '', '']", function () { + expect('.'.split(/(((.((.??)))))/)).toEqual(['', '.', '.', '.', '', '', '']); + }); + it("'.'.split(/(((((.??)))))/) results in ['.']", function () { + expect('.'.split(/(((((.??)))))/)).toEqual(['.']); + }); + it("'a b c d'.split(/ /, -(Math.pow(2, 32) - 1)) results in ['a']", function () { + expect('a b c d'.split(/ /, -(Math.pow(2, 32) - 1))).toEqual(['a']); + }); + it("'a b c d'.split(/ /, Math.pow(2, 32) + 1) results in ['a']", function () { + expect('a b c d'.split(/ /, Math.pow(2, 32) + 1)).toEqual(['a']); + }); + it("'a b c d'.split(/ /, Infinity) results in []", function () { + expect('a b c d'.split(/ /, Infinity)).toEqual([]); + }); + }); + }); +}); diff --git a/dist/bower_components/font-awesome/.bower.json b/dist/bower_components/font-awesome/.bower.json new file mode 100644 index 000000000..7f6d0e3ec --- /dev/null +++ b/dist/bower_components/font-awesome/.bower.json @@ -0,0 +1,14 @@ +{ + "name": "font-awesome", + "homepage": "https://github.com/FortAwesome/Font-Awesome", + "version": "4.0.3", + "_release": "4.0.3", + "_resolution": { + "type": "version", + "tag": "v4.0.3", + "commit": "dc23a94e16a8daa3cbb3c7fa34d63e2812637b8f" + }, + "_source": "git://github.com/FortAwesome/Font-Awesome.git", + "_target": "~4.0.3", + "_originalSource": "font-awesome" +} \ No newline at end of file diff --git a/dist/bower_components/font-awesome/.gitignore b/dist/bower_components/font-awesome/.gitignore new file mode 100644 index 000000000..63dd5211c --- /dev/null +++ b/dist/bower_components/font-awesome/.gitignore @@ -0,0 +1,32 @@ +*.pyc +*.egg-info +*.db +*.db.old +*.swp +*.db-journal + +.coverage +.DS_Store +.installed.cfg +_gh_pages/* + +.idea/* +.svn/* +src/website/static/* +src/website/media/* + +bin +cfcache +develop-eggs +dist +downloads +eggs +parts +tmp +.sass-cache +node_modules + +src/website/settingslocal.py +stunnel.log + +.ruby-version diff --git a/dist/bower_components/font-awesome/CONTRIBUTING.md b/dist/bower_components/font-awesome/CONTRIBUTING.md new file mode 100644 index 000000000..cc2530cd8 --- /dev/null +++ b/dist/bower_components/font-awesome/CONTRIBUTING.md @@ -0,0 +1,75 @@ +# Contributing to Font Awesome + +Looking to contribute something to Font Awesome? **Here's how you can help.** + + + +## Reporting issues + +We only accept issues that are icon requests, bug reports, or feature requests. Bugs must be isolated and reproducible problems that we can fix within the Font Awesome core. Please read the following guidelines to ensure you are the paragon of bug reporting. + +1. **Search for existing issues.** We get a lot of duplicate issues, and you'd help us out a lot by first checking if someone else has reported the same issue. Moreover, the issue may have already been resolved with a fix available. +2. **Create an isolated and reproducible test case.** Be sure the problem exists in Font Awesome's code with a [reduced test case](http://css-tricks.com/reduced-test-cases/) that should be included in each bug report. +3. **Include a live example.** Make use of jsFiddle, jsBin, or Codepen to share your isolated test cases. +4. **Share as much information as possible.** Include operating system and version, browser and version, version of Font Awesome, etc. where appropriate. Also include steps to reproduce the bug. + + + +## Key branches + +- `master` is the latest, deployed version (not to be used for pull requests) +- `gh-pages` is the hosted docs (not to be used for pull requests) +- `*-wip` branches are the official work in progress branches for the next releases. All pull requests should be submitted against the appropriate branch + + + +## Notes on the repo + +As of v3.2.0, Font Awesome's CSS, LESS, SCSS, and documentation are all powered by Jekyll templates and built before each commit and release. +- `_config.yml` - much of the site is driven off variables from this file, including Font Awesome and Bootstrap versions +- `src/` - All edits to documentation, LESS, SCSS, and CSS should be made to files and templates in this directory +- `src/icons.yml` - all LESS, SCSS, and CSS icon definitions are driven off this single file + + + +## Pull requests + +- Submit all pull requests against the appropriate `*-wip` branch for easier merging +- Any changes to the docs must be made to the Liquid templates in the `src` directory +- CSS changes must be done in .less and .scss files first, never the compiled files +- If modifying the .less and .scss files, always recompile and commit the compiled files +- Try not to pollute your pull request with unintended changes--keep them simple and small +- Try to share which browsers your code has been tested in before submitting a pull request + + + +## Coding standards: HTML + +- Two spaces for indentation, never tabs +- Double quotes only, never single quotes +- Always use proper indentation +- Use tags and elements appropriate for an HTML5 doctype (e.g., self-closing tags) + + + +## Coding standards: CSS + +- Adhere to the [Recess CSS property order](http://markdotto.com/2011/11/29/css-property-order/) +- Multiple-line approach (one property and value per line) +- Always a space after a property's colon (.e.g, `display: block;` and not `display:block;`) +- End all lines with a semi-colon +- For multiple, comma-separated selectors, place each selector on it's own line +- Attribute selectors, like `input[type="text"]` should always wrap the attribute's value in double quotes, for consistency and safety (see this [blog post on unquoted attribute values](http://mathiasbynens.be/notes/unquoted-attribute-values) that can lead to XSS attacks) + + + +## License + +By contributing your code, you agree to license your contribution under the terms of the MIT License: +- http://opensource.org/licenses/mit-license.html + + + +## Thanks + +Thanks to Bootstrap for their wonderful CONTRIBUTING.MD doc. It was modified to create this one. diff --git a/dist/bower_components/font-awesome/Gemfile b/dist/bower_components/font-awesome/Gemfile new file mode 100644 index 000000000..499bcea70 --- /dev/null +++ b/dist/bower_components/font-awesome/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem 'jekyll', '~> 1.0' +gem 'debugger' diff --git a/dist/bower_components/font-awesome/Gemfile.lock b/dist/bower_components/font-awesome/Gemfile.lock new file mode 100644 index 000000000..b677d9c0f --- /dev/null +++ b/dist/bower_components/font-awesome/Gemfile.lock @@ -0,0 +1,46 @@ +GEM + remote: https://rubygems.org/ + specs: + classifier (1.3.3) + fast-stemmer (>= 1.0.0) + colorator (0.1) + columnize (0.3.6) + commander (4.1.3) + highline (~> 1.6.11) + debugger (1.6.0) + columnize (>= 0.3.1) + debugger-linecache (~> 1.2.0) + debugger-ruby_core_source (~> 1.2.1) + debugger-linecache (1.2.0) + debugger-ruby_core_source (1.2.2) + directory_watcher (1.4.1) + fast-stemmer (1.0.2) + highline (1.6.19) + jekyll (1.0.0) + classifier (~> 1.3) + colorator (~> 0.1) + commander (~> 4.1.3) + directory_watcher (~> 1.4.1) + kramdown (~> 0.14) + liquid (~> 2.3) + maruku (~> 0.5) + pygments.rb (~> 0.4.2) + safe_yaml (~> 0.7.0) + kramdown (0.14.2) + liquid (2.5.0) + maruku (0.6.1) + syntax (>= 1.0.0) + posix-spawn (0.3.6) + pygments.rb (0.4.2) + posix-spawn (~> 0.3.6) + yajl-ruby (~> 1.1.0) + safe_yaml (0.7.1) + syntax (1.0.0) + yajl-ruby (1.1.0) + +PLATFORMS + ruby + +DEPENDENCIES + debugger + jekyll (~> 1.0) diff --git a/dist/bower_components/font-awesome/README.md b/dist/bower_components/font-awesome/README.md new file mode 100644 index 000000000..874d76c7e --- /dev/null +++ b/dist/bower_components/font-awesome/README.md @@ -0,0 +1,77 @@ +#[Font Awesome v4.0.3](http://fontawesome.io) +###the iconic font designed for Bootstrap + +Font Awesome is a full suite of 369 pictographic icons for easy scalable vector graphics on websites, created and +maintained by [Dave Gandy](http://twitter.com/davegandy). Stay up to date [@fontawesome](http://twitter.com/fontawesome). + +Get started at http://fontawesome.io! + +##License +- The Font Awesome font is licensed under the SIL OFL 1.1: + - http://scripts.sil.org/OFL +- Font Awesome CSS, LESS, and SASS files are licensed under the MIT License: + - http://opensource.org/licenses/mit-license.html +- The Font Awesome documentation is licensed under the CC BY 3.0 License: + - http://creativecommons.org/licenses/by/3.0/ +- Attribution is no longer required as of Font Awesome 3.0, but much appreciated: + - `Font Awesome by Dave Gandy - http://fontawesome.io` +- Full details: http://fontawesome.io/license + +##Changelog +- v3.0.0 - all icons redesigned from scratch, optimized for Bootstrap's 14px default +- v3.0.1 - much improved rendering in webkit, various bug fixes +- v3.0.2 - much improved rendering and alignment in IE7 +- v3.1.0 - Added 54 icons, icon stacking styles, flipping and rotating icons, removed SASS support +- [v3.1.1 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=4&page=1&state=closed) +- [v3.2.0 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=3&page=1&state=closed) +- [v3.2.1 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=5&page=1&state=closed) +- [v4.0.0 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=2&page=1&state=closed) +- [v4.0.1 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=7&page=1&state=closed) +- [v4.0.2 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=8&page=1&state=closed) +- [v4.0.3 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=9&page=1&state=closed) + +##Versioning + +Font Awesome will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format: + +`..` + +And constructed with the following guidelines: + +* Breaking backward compatibility bumps the major (and resets the minor and patch) +* New additions, including new icons, without breaking backward compatibility bumps the minor (and resets the patch) +* Bug fixes and misc changes bumps the patch + +For more information on SemVer, please visit http://semver.org. + +##Author +- Email: dave@fontawesome.io +- Twitter: http://twitter.com/davegandy +- GitHub: https://github.com/davegandy +- Work: Lead Product Designer @ http://kyru.us + +##Component +To include as a [component](http://github.com/component/component), just run + + $ component install FortAwesome/Font-Awesome + +Or add + + "FortAwesome/Font-Awesome": "*" + +to the `dependencies` in your `component.json`. + +## Hacking on Font Awesome + +From the root of the repository, install the tools used to develop. + + $ bundle install + $ npm install + +Build the project and documentation: + + $ bundle exec jekyll build + +Or serve it on a local server on http://localhost:7998/Font-Awesome/: + + $ bundle exec jekyll serve diff --git a/dist/bower_components/font-awesome/_config.yml b/dist/bower_components/font-awesome/_config.yml new file mode 100644 index 000000000..d68d5faa3 --- /dev/null +++ b/dist/bower_components/font-awesome/_config.yml @@ -0,0 +1,58 @@ +safe: false +port: 7998 +baseurl: /Font-Awesome/ # Where GitHub serves the project up from +url: http://localhost:7998 + +source: src +destination: _gh_pages +plugins: src/_plugins + +pygments: true +permalink: pretty + +# ensures SCSS files are compiled +include: [_bordered-pulled.scss, _core.scss, _fixed-width.scss, _icons.scss, _larger.scss, _list.scss, _mixins.scss, _path.scss, _rotated-flipped.scss, _spinning.scss, _stacked.scss, _variables.scss] + +# used in building icon pages +icon_meta: src/icons.yml +icon_layout: icon.html # Relative to _layouts directory +icon_destination: icon # Relative to destination + +fontawesome: + version: 4.0.3 + minor_version: 4.0 + url: http://fontawesome.io + legacy_url: http://fortawesome.github.com/Font-Awesome/ + blog_url: http://blog.fontawesome.io + twitter: fontawesome + tagline: The iconic font designed for Bootstrap + css_prefix: fa + author: + name: Dave Gandy + email: dave@fontawesome.io + twitter: davegandy + work: + name: Kyruus + url: http://kyruus.com + title: Lead Product Designer + github: + url: https://github.com/FortAwesome/Font-Awesome + project: Font-Awesome + org: FortAwesome + license: + font: + version: SIL OFL 1.1 + url: http://scripts.sil.org/OFL + code: + version: MIT License + url: http://opensource.org/licenses/mit-license.html + documentation: + version: CC BY 3.0 + url: http://creativecommons.org/licenses/by/3.0/ + +bootstrap: + version: 3.0.0 + url: http://getbootstrap.com + +jquery: + version: 1.10.2 diff --git a/dist/bower_components/font-awesome/component.json b/dist/bower_components/font-awesome/component.json new file mode 100644 index 000000000..4625d0941 --- /dev/null +++ b/dist/bower_components/font-awesome/component.json @@ -0,0 +1,20 @@ +{ + "name": "Font-Awesome", + "repo": "FortAwesome/Font-Awesome", + "description": "Font Awesome", + "version": "4.0.3", + "keywords": [], + "dependencies": {}, + "development": {}, + "license": "SIL, MIT, CC BY 3.0", + "styles": [ + "css/font-awesome.css" + ], + "fonts": [ + "fonts/fontawesome-webfont.eot", + "fonts/fontawesome-webfont.svg", + "fonts/fontawesome-webfont.ttf", + "fonts/fontawesome-webfont.woff", + "fonts/FontAwesome.otf" + ] +} diff --git a/dist/bower_components/font-awesome/composer.json b/dist/bower_components/font-awesome/composer.json new file mode 100644 index 000000000..49b9b3069 --- /dev/null +++ b/dist/bower_components/font-awesome/composer.json @@ -0,0 +1,27 @@ +{ + "name": "fortawesome/font-awesome", + "description": "The iconic font designed for Bootstrap", + "keywords": ["font", "awesome", "fontawesome", "icon", "font", "bootstrap"], + "homepage": "http://fontawesome.io/", + "authors": [ + { + "name": "Dave Gandy", + "email": "dave@fontawesome.io", + "role": "Developer", + "homepage": "http://twitter.com/davegandy" + } + ], + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "license": [ + "OFL-1.1", + "MIT" + ], + "require-dev": { + "jekyll": "1.0.2", + "lessc": "1.4.2" + } +} diff --git a/dist/bower_components/font-awesome/css/font-awesome.css b/dist/bower_components/font-awesome/css/font-awesome.css new file mode 100644 index 000000000..048cff973 --- /dev/null +++ b/dist/bower_components/font-awesome/css/font-awesome.css @@ -0,0 +1,1338 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url('../fonts/fontawesome-webfont.eot?v=4.0.3'); + src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.3333333333333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.2857142857142858em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.142857142857143em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.142857142857143em; + width: 2.142857142857143em; + top: 0.14285714285714285em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.8571428571428572em; +} +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eeeeee; + border-radius: .1em; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: .3em; +} +.fa.pull-right { + margin-left: .3em; +} +.fa-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + } + 100% { + -moz-transform: rotate(359deg); + } +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + } +} +@-o-keyframes spin { + 0% { + -o-transform: rotate(0deg); + } + 100% { + -o-transform: rotate(359deg); + } +} +@-ms-keyframes spin { + 0% { + -ms-transform: rotate(0deg); + } + 100% { + -ms-transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); + -webkit-transform: scale(-1, 1); + -moz-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + -o-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); + -webkit-transform: scale(1, -1); + -moz-transform: scale(1, -1); + -ms-transform: scale(1, -1); + -o-transform: scale(1, -1); + transform: scale(1, -1); +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #ffffff; +} +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video-camera:before { + content: "\f03d"; +} +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-asc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-desc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-reply-all:before { + content: "\f122"; +} +.fa-mail-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} diff --git a/dist/bower_components/font-awesome/css/font-awesome.min.css b/dist/bower_components/font-awesome/css/font-awesome.min.css new file mode 100644 index 000000000..449d6ac55 --- /dev/null +++ b/dist/bower_components/font-awesome/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.0.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"} \ No newline at end of file diff --git a/dist/bower_components/font-awesome/fonts/FontAwesome.otf b/dist/bower_components/font-awesome/fonts/FontAwesome.otf new file mode 100644 index 0000000000000000000000000000000000000000..8b0f54e47e1d356dcf1496942a50e228e0f1ee14 GIT binary patch literal 62856 zcmcfp2Y3_5)&LBzEbU6(wGF`%u_do$I-wUs=poc3^xzP>t859|l91%ydy%{4ZewH9 zLNU#OK%5)jlp7M#adH#VlN(Y~MSVYG)7F`Dsts8mQIv>+ztD)dFw+9OVG%`1 zdML`ns?&x=Qnp|IfM+dm&(}ePcdqmf37+Ghm#p%f+FVKQ2*chjkzF#ZB~9w-bef!xGBr6D7h{6UGOP@t%*!8rhr zqTX&D_txFJckW8F88SgJDOYWQiq1}9HpST zU`<34PZ)C!_3}_&M2)6kC53tq%16Wv<;B!kk^fL$a$g&o8ZTNrRL|U3FQqy}Aw%^t z%FjbIl=r0M9>Z`rYKq77t>{++@-k0@oM~*1+}p2(7`Q4V*n=HYq=vsI?g5v}-nP z3|{}}ibb1(*R0;YdDD}@+q7nj-e?F6nlWp}oWMD=X3yOms||yGW^I(#9B4HL0`>*2 zG{Pq6qjlCmi#Eba+D94TAv}p9V_D5%k=nR0b4*~E)oRv<#|upiMk~z0GGmR=Yz-V5 ze^pq5HgIj2Au?HKwVD>qoJsnJx#u=RZ=|+Tk5lVmJ2z1#N=q3aw}vu8YK7c-N>4=y zwHEjdq-Iky;2wVdD3u7c7HAy@>636rQ}I+R6-Jq%%_eFi6$}s_rB+ajpcD*stEugP zo136*FtrWZo1wQ}7%h+r0@$R$MYWppE&yKBVk^ODoieQIXI-PMCWPv3^jr9p7*cDDu9q6%xx{?3;;b@n3omixrmwx*YNmZf9p3xm@i;8 zp?TpJjUB@J0D^@;Vq@WEgcj}}s2gf=U*-SLs=qz||El20$!O-RlsfnS_J9)6lK^rf z@F|+|fem;DctSVzuQ6lCs>g=*`}C{(m-TP#-`gM6ukSbXXY`l%AL#GuKiB_u|L6U` z^xwJVb4z_|(yht2X53nKYvZlGw+y#3Zk69U@CS95u-8E9*x%q${UiIw^e^w<+#lK> z-M_Ej)SuN~+27uOroXrU-Tp88`)^UVM&1epcn{s0b!+*p&9_2tnQmp>swD94ennAt zcir7`_tDR9d~W}I%Sf-0+(^%nvXRn}u#+RjBRxinMp7g0j<_@8_K4p{{5Im&i2f13 zj`+pr(-A+9_-Vw=5kHRjVZ`?%z8i6aJ1^|@`u}w?=l`!y{JYkcahKF7zYy(4XAHaLAh7>kswf;WDJ8 zodnW*&mk}LA4ATyzs;HS z&jMIk)X1SUY8WQ8mk8qz!5gX{ac?|#KNXah-`{R{t;jx;+arrw4mTM?C=b`)g9B|K zKbe$=Z!xqbc>xxr!#G3cIJ_43-sk>0XiMsaXE3e+56S@N-W&nebhy1GS=0t{!`!CB zeXl$`20SDCO)=z#yl@A)%foXM<_FJ&aY(!S?qN9ajLc&>wDpF%>BD`=97%ujZX|^{ zkUJb;(Bvllh3Ak$Tkm1o9O@S+z@h#=rtsbrEayd0}DguL&kx00m+ja=Bpt$)C)Jj(+GE#@N5{qN_YooPx`~Xe7HP3 z{%{$_+eqqQIN>I3Ngv^P)=&zdhx-v8M)G7X!|w&{r;s|*7v>g7Gy(!cXqP3lRov@8 zR1fWh=MwT9Zqok0{>Y@@?`{gwSN{7?L`gvE7m2*?lX6LUm1893w2Pdz9?n{^!(W2e zdWpaFl9b@u0BLprBcj#q)KgjW@7iqlGG5Yvz*k2E1b+8G7f(?i1&vA9XxDLyUk5nmBs6~80?xA;He-^DJ8RN^C1NybWMO6ExxOV&s>OP-SKlxQUu zNxCEtRJdwMgQQb(MDmQ}tmIiqujCEMHOY0!HkBMipnS7>{u``WKCv$?i#JtM9$^4u7g87d5nYqQ>kup*r>4Q>U zI$1hRI!8KRx>mYFs*@&5bEW0dI%&J~sPvTdy!1usRp|%PFQwl}f0q6xb;-PBD%k|t zY}tI-V%aj;YS{+aQ?dwIjLaxYk`>BoWsR~9*)iEk*+tn)va7OpWS_{smHjSrdP+V0 zJk_4#J?D9@_1xwe?HTK7@=Wl|@+|Uf_B`o%#`BWri=J_T=4`v|*&UBhl-L)Zv5p0%+J>@(~s_AL7X`wDx7eUJT&{SSMK z9pETV%t<)~r{X4Z^SBk<7A}m7;^H_fm&|2x`CJ88%QbUt++pq*cal5LUErSMUf^El zUgJLCKIVSme)FQdBwi!E`Us0Q z%p9T98WOazMw1pS4`!>y8fGSUh&Ik-O^&x{%~AT;IIAusHq0EYwdzPtZ?PI<%-T3( zf;Poyj0@2lgv1zcHAY2Q^wEZ}*a%}ZXpR=04ir-WpbZI&wOaLYTC*`MGSZl6h=r8Y z4d>%cq(*NDHzt{4!;(WH^yY|Ityyc*hFL*fHES(8GA!v5YmA7AiVce8e_;!6kC&7Z?Hyy8O0n%G}drq zY^2^A7ORi2YLl!XIxW$Sg>0fe(yD_8(T0#%Z4_w&Inczd&{N0@YP37MFWzF+MkX06M(8q>71~9GMQF*2ge2%AwMG*R7f)W-5CO{_W(pxQ1Gtd{5P-01VNw=dm{|+^ z6%j+0-eT37Lc+r$ViLp5kx^l=IKzeEl&qvF4E7NA%LH2ey@o@10m4vTyAQN~fSq7A zx?gWNFHF`H8*d3AI~%7r4CUPWFH{<1gk*m_30u(tfF`iWB#nqQTC}hv2E8F#m?SuDFTQn3UEkkc8@TWC!-F{GC^ww z>q*$~q;*EKK82V{VgW}(B4CfL)4q56 z4)D)xH0hF~^)O1fFcUYy3iJruY7hufKutIFVd8R^gr`Ecp*I_TDL24)U$r5ORbRg-pCjNXR?8@hRjlg!)^B z(D!dOu%iM74)q`)qGOHW+C($Zqs|&;iLn3^gGC89>$Oo4U_&EF=f-R>g=zQ41JxU% z^ai~(IaX`22o=$0BPn|0z*CK8 zK%DqkW2^;?Z85-a0Z6ni9$1JOKmq#-j|FR7G;j-Zd_)ZF6-)}K?p{V%Lg*B4TBUeba0p4h(`{lkhnUa;!S@mlEwb3uRAAna%X|R34lqnNUbFX_%$pF{0bXxjWdRmGt^CFZcG*MWq&*% zpD-JDPJjsSWiSA$4WFQ~!(L z(g@%$q;&`!M=`(;0H;FcJiPEeUTy)bGXu%#O;$^MxH}UvXTe-kd`b#g8@(3xP*30x znc%M+5eqCjy*4&-n6xnX2oC%!5s^Uj?t@SuO@S=#uW(bx z{WX6b2|^FDjXG;w?7RqzWiB8Wa4|QJBTGftngtFZz*C@qy(Q$Y1K?iO@DUL*ch+1% z9wK1j&>$1McLEb&Zk8+5#cF{jf&aTxfx3yPAYib-S%s<1oju2WfRYkWB~Tuak9)I+ z(-1(skh!xT*2bHo!{JN-dNJ<8yjM5m zG60rH7zk-~uZGNixK`kLe=CruA#>*j!96b-j;Z)?t?(j4`6Spia^GJE{4Ojx680Zt zNWe8%t069;H$XAk92OS^LR}2VREDV856=$Q!%mO|6<}C_6UCa{zd}W<5upDiblg`Y z4Cvl7f*bc0-6U;-JxByu&zNWdaxxqBk$}(fNs-__0UlzBNj3priZ@%}*dQl4?7A@u zxFO-}z(C>X2fTOs4u7+;J0*%HiJsMQxqoBiu59bC{I)* zIwpEv)GK;ZbY1kl=qJ%1q5%)ugY$R_l;6D`VIDej?~k_t(Uq#ab(*CcOB-jjSFxlRYtLG(g8nl{qO zbOHT5{ZCLqIVOM^&rD@zGV_^TOav3dn3%)Nr_5K(_smbsZ;XR+Nxh{3(y`L%(je&q z=^E)esaBdKO_%0LE2WLn1JX|EJJNqkKa+kfy&=6R{Z;m$EI>A1Hd!`RHd8iFwn+Af zOe@pN;$&u7o$Qe8lVqKiD_fkJ-=Jui1W386V`Pb1S)E zZZ{Xs={O@7&!utMTpf3Udy%`wead~q-Q@bYKfGjKDz6z{L0&7o9`}0EYlm03m(I)J zmEe`?mG4#O)#laVb=0fN>w?#dUN3vS=Jl4>2VS3feeLyw*Uw(Rc{#l9deh#V_egJz z_ayH*-iy4Kd2jIE?ESR2*4ylzxhxHlZ~0u+4bSNe2Avwqk&^$DHRv=KS#CD3;S~8SQm|;x zN%uXOg<%H!6sOWpT07MECb~&~iaal%Kr~kA@W=0ly z{t+$Uxdi~XHN7!e%}J9R(_7UXGlAu{@LgPTdU`T9mC4D=%h61g=2Yj|)i)V?b+ui? zE#uW(1@DS-MfI`{o?I@T&abi;)~M_?7x@=n*uipt?Z;r>c-GlBp66Pcnp(J_b~W~k zJU4;W8IE;z9Xr-_5FpZ3`8gH2s@$By{Co|!66RIRN3*C1^>ST?V>+@U!LTF2up`?- zL$|?lw4^nqr~{nKnUu7&6b%lRrZlCsr~{Z@h76@~^htykcl!R`V4$yrCB3Hbq$wn746_@NOa-3Klzp2l^gn2VQjbAuo0?#JQLL z$Mz}bSE*b<%<3&$R%={A(pBfD{9}jO88R43TRRf@j!umu(~;H5a&uR%M853YmDj$} zIQyjET)Xy-no~>!4446Ue9XYDW$(ym^9NXsBiI!j&bBmH*VjYd5uCtsQXS7>`8HO> zDbN}`0?ouLy46Rz8=vn%p8Uqm@ezB}D0m6pght^=)w6thX?kgz2G3qG5zoOZl-P#$ z;62Eu9_V9|U>i5{jy^LBsJUYYou6NrldH_F$f?R#6Z}L^@PMpQjwrgSs={8Q zoOChE&E(fDVqJZ+_^S(9K%?|z4Qv@&$Gd6owP0l%>_y%&IxVx)7#jOLcGPC4#d!g42=Yrv!#JYwQRKph}ax;`_tIz`20);H(1 zsJH++i<8d1wvyoE7px2R-tQK>V~5{WU|KHT4=~~?>;J-zTfD!37u?D8Q>s%Z8#$yy z%h5wD_x>xdywB+ughWP$WMyPzRwT*3=TpiXGn-0FZKbMbDvnhisqR1g!-dcPCCh&K zU-?&5z+T@$$>=nPF5$IkC4LdF#0#)`=@RwFOYj1u#w%4&w-#zI;XGu*dusADPKoOm z8YZ0Itm0}4+W;2`1!=edNfwuq23(9Y^AiBwidZ$*g5O$1LZ$6+E(!Uc|#A>nDKry|{>zcC#+K%kF13+aeB` z9VD9p6UpVd$^V7B9CH{zE9`mIIchS3J(9JvNG|5m;2dy7E#^4~49g)Y8pA2@Lg!dK zg2BOf!)Nnef3=~Zrna)izq+0-OJ%Z4GBT8|Rd_LG9C|4SxZ~=3jfW$p9$pYw$y_dg z$>JhlV>uJMiW^X%#R@E9a470Q>roqx9zaWQErSDbk~yp(uQ0DT&%cNvuP5iE^LQ+u z26PNWna=x2;dpDwYtF2PX<;eXb5R_ zZZpZ*jjdH0&h{xRQ82^3_v)+fai0dznTkb#fpNA>TZj!$wMBp(y(a5G+OcF=O-IX7 zI1yn7^P5|gEmh6+^=fi-zRxzcYPfTi=c-TFqDL>HS)ZW?kxW)_xu>W{<;ZnRKUuRK|0& z{yIfL1XJ`OLv>qeQ+d6Ac^h59pu}O!d{)1 zv*gVuu9H;FWrMuddxQ0v#UA3Pz#$I+SM%g3Mhc$GgAw6?7&+-zJQ9zbG>QEFIth(L zBY*uBja2)zlewX3ESktVZS|5(mkM&oHz$Xv$b>E&ZkH^c3ZkKeyP{@`J>81Zl|K725KKL~og7cTUw&+r2C zUk9>oB)d(Z#5JNP*mUmDq4TywX6_8%+DKj@yYsN}P;F;x zs~Sy06X}*#uDQ7i4t1y4@e^&gBNN(#@|4_eym;lN^{dj7Q_?EUGMmj-qU3N8NR(vr zL5@U0AW!DyaDfW~n7L>qoU7ycb%~=uC}_($bO;~RAg|+gl_}Tm%SPM9pFM`C+p(U`f$Ogj39`p#D49F9Oe2B)Y(1=eW zw)bneg>cL|gV(T-@p*5{tE=Jcu_#{Qxp*GXIvt3kkYHpQ3rMZzl>31_u>s6-4t1k$ z+%4rq9}T342VUdi$!t^dQ!_JRmu7%?geCz#$k7y78#|!3og3_v;<;Rny}YW5!%{qk zYr=}g#4>emYj$g9vy8LVs?h8`L_|TiBLNz~6T}mIn`7Q#x%%eXmYM^ywlbt>Y*KQW ztPgGNM5|#@Lho##(bo(L9oRr~qe#cANDc%f=kjIw`MHHTDlBJG(mA{ekB4g&=UR+@ z#y>k2b08anAWukZCeRZa(ch0ofCOX(Es0wN+K`%qt+#QuZ7_-y0m}#2?n`dsD*wD% zU9TxGD=jNm!ZzETgs?z(%&2dH6S29assTs?*$2o*DW}7G$(=zkCn=n0K=g91j%PTP zO^O&KdH%vD8V)3XPz7L>;2B8w07~qv;%G|;IoyGV`0yOvTG|Z!pBsQ#a448*<@V{7 zdf2gEhBIedl9SbV5}wF0Z(rH8R)gfF3J%|GPxzE<#INuQA;=Fuj>54gr^1)E;a_nA zo)4mW8(@oc8NVA2@UCNk;D%})%w{#z2H@ok=K_g?v+@cKVge`%egi3pAfR$7s)V8% zDeAC@I!=iS?|Kv_iSmi9WFEB;;){P5Rf%dKM4(>OC~6j+5}g+P=`qz~g~xw9Zi~l? z6U67mcO<+dT5?YEC%uhsrC(z|gAE zO*vJ0Soy8esY(oZgqQLER6n4etX{4*s1K;GsNYi~jhAMuW{;*_b1QI4;QGKH$2>CT zA7i<(=f?Sr+dQskyn1}e_?r{PPpF*GHsRt#zlr~zR50n=$@LGNnX+igA5%|F+cqs@ z+S}6~n7(}aZ!^p@%4hsObLz||W*(ijYF6oN$QX$5KDr7zAHmywn^DlpJ_O|_m=Lh-A{Et-MyoGSNERokiok) zBnhB3NFqWKByj{Ii5OXtL=iv-I)VcRzH|jku>?yL&Y*4VU{JsS#rOmaeBcup%p(vg z?BW3W4M&OsA3!q@+*i8Vuj{V(uR|WXD@)op>iqEmJe@|bq0uaUO$x21Z|quaWJ_xUXAmZ_~hhx4bGFsw0wse^@d)0B zL-DjAP%gua%Yc&7*ptG~HMb>n%yYV^Ir+quNu8Y~X zOsAO}fxX6IZ{=QTe4}1~-O+ORpvERWcIMrGol^hUixhq6Nu^Kwy$j!Uz@hXT4-9Ss z-^eat$rCh}7lHN*%g%HL&}$Su8|+c)fPpL~YD3OWLx-U)QRDO)^r8pth-2Z11unc6 zgng%-ae6tu=(e_wW5-~S1W_f(E39}MY+<0HH}t}`?3|LK9Q9xyw$l+A#;7pmon0@m z&K*)1ESq+ndV%!`g!5xSUcduLyEub)22bZfY4K@?Qx%R1r~Nu#$Db%*0|u7If<;f- zZs~|Wl!(S*4>TT2kOs?S>p%Q{+3%`Sh&B5C`;XrEP=ho`23o%ajYA%X+By!lcghCs z(t*>G`3tf5iS25v9E+7>u>TlY=(eddSF1{x5@z+(?=Ec9VE;d`68_zm&3^yMUl5~Q z0Git}{%n4T8P1e5L>?Gep2ptkLk#cJzMcm|(|{by6<_nIywA5V(E)G8Gcom+3bm`G z563%p(Fbx;4q8>~c*j#Xi_WWWENE06tM5GgA^R;KAldIYrnu%>=<-IpTt0YLpJO5Z z7ka_5=ykNkF$!&QjdCo4<9+{Y{}-4YM?Pfn-Sr?2iLE?(P=OM*pd0w2DX66fl@N?-1iD^%I(}!F>Y{#DE3uA#DGd2hEe5<#MzbG*8eJ9rAVS*a7>X z{S`8p!61R*K0CV=3?EN|rl+Y>-AblM$u#nWsCFL|0B zfQG|)pZ4~I6JVA_-Cz?4mQ3W`hJitlTLhF*gLObK6@qDS+lA0x(4E2J0agpr&cu^; zCO{MD_+OBcSu~yntMX9y*I=$xBgAa|S3PuJ@wbLP?TrDFLn7oI!1w?W6b|fFfXJWR zs>T5*;3zvdesBW5jGjNr;s6}*4v+5OI|y>`@(7+gbxs`u84}+uPY@vw00iu76xufo z;xcky3)%Z&;>+Yhm+!$8%J?!scS9CB;mhtZ2z){+m9XdqJo!a-xeFw$i9EJ~O~`HB z##U^V3ifpbIY!5;!OjkR*D9R>68VYgd@_*MUtkE$$-fkUxcc07c}E{~7;XvDpX)Cb|1|XFuvZq>JsB#)PveQe{;jxBiN^8{5K0jUrRqVzDg~18#Ciz@>FQUv zymy! z&*Od810Fl&u{>a&NYRqnoKmjF>yBohOh1`&!vECeGZ#-?l2ulhSKE~}#We+0>ac&U zetlbytST=DEOI$HMPT2?V*?FMarLpa{zkN(ZYfS}NLFDp%px@Hdbg?*+HWKXULd8 zkEK16c|6zUdZ=x9l%!V#N--vs)1Y?7`7@ zUn0ko6}wEv0^s#bf$8Y;nt{g#G6c;O9Rxkp~37xp$cQT7Cj!TNVhT`^& zI&4Hw_&KKS_Q{rzgsVT3nbUxjS!=s=ByFFeTQM)>Kqhz5aopk1G=ntHm(bZMG8dQ$BhNn1}_Fh1}7Nti)0c zsT@ogRyZ#PtP12$h;{@IwrJG15JZTZim@zu2-s#H3a(^DF9b*f!~-`SXB4TWX_;v% zT*RcM)i;-FDx{sz1Pp>3(E_#;_tAw?r_B|uIG=Ss?X=o8Z{QexDBE<7`o%{7?Ua9oUL)qyK{_Ai_VIOP#S7N&Z?ckpe>SiZNU9u zm_q=i4bJZ5(sVGj!PB!f7mo=XL{82L5inMgk&7V{T*SK~8Nwgw=%`(Z+g00lwVjUA zU=<3WUD{k?Dq6tekKu^y$hJ1`S7AGt=)v}92iHh2woB0rmiQX{&w_)RM|6e?WpRxG1qwgX1Z!msyPF7Ub7d7P6Vlc}3fyKQX z{8za}`FR?A4PT@4^9plwl!99goGkcu9*=ILU}-~rO?{;X|K@0ah;2_8fQ@>SAE*Hu zm0Ehb1*Q3A1^#G9oZ@s=Z~7@U&T;h6C(|Pi z>r_B2x`_Sz(lt28)kCN2v$jPmT?xPQJ9rqtDh3Y{nDII?+Y{^5u5Q$qRByH=X89*( zW+qsbz#re{>&mNY!JH4q<+i%|_71QcjvmY20Be`s_Y9ba=Ca)^9*q@#$RFGQTd(6C zD%WBR767mVjOD@V9ovsqp^2K>2HSzmI?N+AtVd2c@Vk*_I(IXT8ZbX?y>VB zUjx`hNA3vvLF4-_R%7+suyd>U8$5c5_dOFpf9J3&TGE@)C^juSC%r(E5|OF3M9T2A z8F=ALyha5M-v?g!X1a!$w-VTSu>AxDq`vRwfu|HHXh4~0-SQeQgF!}1ZYz~VPn9c zflBaRv=`n3Qn*Usc#Ek45eF0^LSR7lb6Mh?HnDpSg`cyk1F(JR%Ob?7Vgyf{qpy_(zgvuS>Vj=cLo{pa z>7>`QufDBBFQFGv3;F@B7jX-I>9Oo}NgLE_GwF{*7W7V4osfp`C!~n`D{ zw)N2Ge`)&ziIhHfGEX#uH_&MpKf(LB?vesIuAl_mzgzL^#-FF3QCH;Vl;)~*24l45 z5hQEJ5XpdL?T;vL1Qt`RP}9%>a6BA^|X!|NjdB_-jxI_CZ_l=Idxa zYiv&H$kZH3Ka|;-Ec<2Ut6=@}QDUDhSUP#7+LCO}G^NX|nW;%eh5%56KxP0ZU4iv*KA7w1xTwa7;q_g#*D8$PI$hF$~8E;@fbZi2er?M%mste&UVe zXw>l^U;pv=3AlcEd7Zho235`~JX|gRb zKMD8VG5SSkg(gI)?#yI@*VMn7sL4H8YOkr6)!UoP8&pmwgM1I4LNhLF(2)Uk4S`SY@Fxs`Oc(;0h69>rvKnWwBS-<;xgEr(x6DibxmxA2GpmIW%yoQloTB&TirQB-&)3iy;JKCM^{C2fZQ!-8vmGcos@_>` zs?06jUahZ9ZjxoybQv>rMOIl>wlW*yIdawc z1=gI%9Q>fsugF}o-=uuC4DGI?OOHNR`nu}nH;VJ$(-gdSwdhq6NdZ#d`u?6~~Z{9B`t z1-wD7iVv{1TrJ$)^S%f-D(W5jPFReasvb;xyJU+{ge@XLF!sW1Y>t#pxHf&n1 zT#>nH|1Pz8XL!_BlgzYrRr(xN=QBka^;w~<(os*A)DqVV3{f`x~wu*<2rlCTY(;`{I>jL zIg(cYQuReK+EM8DP0?Fb7i+$1ey6Rcv#0a&>5I>wJl%P&@mbk{muvs|59Qaf*EhbW z_U+#I{v1%Pj(mLjABWnTWxgjboH*Xqepc3gw(i1Z<%PWN^t0;pv+-Sq_cH?QCUG% zdPQ{U<|=F`!^+a9%Ut<>^NXIy4^bDT=A~pM$7FvlUt%w-s(;S!0?Is#=3GHno8CWo>lpI)FKe$jT79zST+OkX zwj*_?YR}i6x1XsyQCHPo(E_mQ%IeFS(o1y3!G*H?$*YP&RM{3=S)>NP*O)ZkUffX9 zT;l&u;qy61(`3n|nI*aE+#T^)mAc-5XO|S1md4@P{+a8x;&v0(YMUovWmkUrJ&Pu zXoQi+mlzyVO8Y8*2502splvA@57<9pE;b(RGHHC@z@yN7Q&))11UB+fcs{K&H5xCf zKDlFG%!H&Hbw@N1lr{f|?xO7oSi+$#0O~rDel$eo146*S?V*`hq6(0H%NP%`pACJIXr6*_&%wUIKAOx$>g;p&(WnhH6fYKMq71sza*elGHFyzT zNPIVF5n6Pb9n8$&3wSgMoXv3B$C6Mh1fewGk~#e>zp;A#;b65xG}uIkv|TbiuX_H{ zk&Epb2jy&{55H9X#uX)4CZOX@#Zq2#rw<$&plbvIOi;aXCP=0bJUn3c-RxUQ+%1X* z{>fL~SNpafs_Cq6Q#Z8rzSI7;tgaj)tW-6%1zF{q_Q!hHHYCdG6KgDHrSE2tnfv2@ z*#3!n`zLrG>Rg06WEV2S+hbHQ5ecCgnnkz+d`6wy7t4G@cPx&bJ`uY72A&*2kiR() z6bXoV6U+i~@qib)t=M{V>dOo`ML-S4(`fXOqhDdqDM`!8!N1|({Bm;AN^(==Jist4j@u&|VHkfH@Du$@Qy2AQ$ zyS=B!4Apu-Qm z??=AR!Q1>cw5nx=g{6hW@|2gSS+|amKUv#qsXH{+_oKfB=iXcIlJfGBa)=elxEVFOi~iUHd&I=pcASXucdT%& zI1%%L?ZgRx=S$9)Xz&P5Vg--jbHH8UD3D7bnD#I%oeT0z8Q3~q@{90U0|W>Iq7TOh z1NXBNgAP&M96-(t7<7ax5CV`lsF`;0Kr{)mF%V-31dg>2)dn!v5Y0Px-e3)^bLR_u zAk-tD0EPi=Wb4oq5)tMOdh~ZfmOf-|vv(;;YY^!I0+^8?SJRo`dC@ukP#kZu9gS@X z7R zCS-&8Ac`H_`5nyExf3wSe-KjId?+zTryShb!;;qltDAkOl@Z$Z084;cCoF^bIV@Ee zi3{;N-Umb2864mq;zq|m6=t(Nu}cM>#x8r?A+v@+MLw**Gn*WdKniw(tq8euTdsi8Zq0W~rrMOat z%m0Qa9T0xxB&|C-8&94BV}cy@fj6lSv`8TpH^P5~fbH1MJPwr1O5YI>fq5L>0N%zO zpw)L380LDgt&xsGhe10dgc}3xt5^u(a<_ofE8Q_ik&>4J5mvKj)0vr&g(IvQf*&EM z=Wz@dRD$rSN=YG=v%iJN&b$_g?5u8v$WA1*LC~f?kA!H=1=V$Z2@4m*i z!)jf11|vI|n8CTKI0gr=6lqxSh(fRxsD;zUZFwYAz1w8iX;p%+pFb`A>8H=%KcT*I z^vK~Cl@~X6uZ!LX%cM?9PfXsuNtT-rdYCFNudJd#gZ+NZs4Z-@H~OP-Um>6O(8DSS zoDRl3UI$DI2g5tT@K!iGt*{MN6a;gygZes?bp@Y!A_yRcap%RV1Aj6_&7Kx;2d?wJhEtaB~olpbt#z|334}xAjCm}zo^*y)xKLutVI8W?{JDyFB1Q@ zZ_8I|ht9Q2;aCbEKK)ESZ-CDnes(Q&ErZV-ejfVF;b+G(wNC)OE>Uz9__G-Nz3=RO zZ6z2L7<36;qB{jz2UcO}R4@MkgsPa&d5c9es2Nn#RuU84VO2XdgMo>XE1Z^x!2y&xJLkH-3zbN3m%kH8KljihAJNb-ug>0nsnuBd*6X?d6;)zd+r*T zW2CS(mmnq)+H`6@{E%?I6J&tp0rb`DATh%L%b^w|O)E&6u#ND-5T68qh?oB|I~X|p z2@cFJ@H7ifZHSfthPe--wSjaqP6Yd#K)hyrfmUFjYbnTCJU^_5+x3N53hR# z%hh$(x|pT}S$1`GUZbk5zWG3NVQWdVrl`BPyIbklk4}H?SP7qr0PoF%gUtaaGMsqM zLWgx1?>y+dy%z!%qyh8|Q3L#d1ncPA3r`1b?*eB7@SU5^Ai{UTK*kTiV-(5hX({SM zd~#Y-s|GzOZEb1-=Sncs(wLU4DMm9C=_P4d;9uOpB&F3gYEqmc8a&F?73#_=d%0bO zOpM)LR8XaQxY8$jL6_Ykc&_$lHY{ri9Qr?lgOz-=rM)PkfMXZbcU8L&C61U zPD*?Y2U(X+x>f4h?fglZc;v8 z4XQz@C<#qQf2!cj1MkmH#g|cl&Gf^j-P?oJ;GFSuJ$4<3t(D<3({U9}#P2J0<+>`p zx+3xLwwx_^=b~}Sgz9{Iih9qH1F>&>{Td2=L3RG-`qbw&u{VB6y{SUe(A4wqAe9D; z`f9Wr?Y)Yw${Ma#zj>8d_#v(fJp@s(pg{&fWG{s1xT8FPC^iG04cu0s8#oI-dO3!C z)ukmxrS$QQT{BkW8dtF1<*URuP!?W^j$vPQNohq19dkwZ{d=g!5q!$w3*la{n*$Ow zUgQWyI(rdKs&+03P}IdMxon^wJ+EegJG^7B0Xxyc%CLKZ^bQ;6Uhr6Dl5U z*PMIqT+i`;$Qlk-w;v`8L*z602~b(lJVNvDvqSXW2=x9Z55$h2lomT!MMg4@`|!bbNtJ)t8(lGj!JyO57)!Bt(Pt>F0vKDH>o6MXX+Gi=;uJYQV7SX zDF7jBiywIBDywp93TsRJOKtE~7}!oUH*Z3GK79S*zYT3e^>CeVRgw<&V*iqIh%Zr9 zSC>^(g0^$Bwx+V7sNNq3IoG3kXx`16S5eTqtNx(10=0Et1*sM6Fn;`rt0#cl1;ImD zSRpS5K1Zw^3dHeOM zu@muwpA$d5brnd044QhC_)A~aod2Qw`&c>N|F)9h5%!0F8W~ zOX7qE><;<;HLE}y1wH9Hs3Sy80@-H}q@3Y{UXUS<^Hw5*49O3md?gc|=`UFU{A{4D zfsjB9Qhx~vM5zLGEd^u)kVD*p1(97&Lo5)Q4r>Qeb258EQC(D1Sf$265MffCpAA7} zu0Bx7gPCP)Q$bU99Yk<~t)Ve9xh6@Kl$@ImT2Y@%PG@Hoq@^K<+=iYnHXFSjIS=0spgd563i}N>f zk6XpVsBFQsxjg;O?JtUpi3k7a-Q)VbjFxT zvu)6pLrfF{lxH+gg0LQH5P-V>h`o9|_GVmVuA$1Ut2S;}6C%w{$x2C4(R#2LTireA zGXTz?AH*3;N=>Ee2jA~L^BMn|dECX&Z;-VqG#0AMi!9bMen9!STMt!W*k*AJ@r}uQ zOwxJ#0$W;D`|_L0>bXB)X}$J3c{4?dR8nb)ib(I>Bhm|}!`AHMjyMjLHP^%~-Mo6` zw)brZ^7oZWu@o)zM-Yj0asEV>kgepk&VHgHWG&VNHI`!fX8XTrvGZR*G;ak; z_W2{SfrA;dl|CgNoxWurPdk&P60(Nu^~V4|r@17&e~&0W^3bDNU~(%E9)-op%uY-c z!!*o*9Hxl@^o{X&85^7#&^;#N47#r>34Hv6m?MO%%Dp&A&K~$gK==z0Z!KOreIzYJ zA#wr=C8jcPn25upDggj}Cvm6@vF=Xfc`&lY418P3?p#c^TJ*y6+{M}Iawy-Ig>1DK zY~u>H*|&zM-k0?pe*4j*+qWO>+>w@4$0gOJ?bxYe?;qVB-jj3QZPzMy(gsqpp^5YA zFX&!-O}Fjd=*mbQYb6XH(N}FJ(GedN384c>e;Q10bUcFbZU6}(KwzBws*Q6FYaiCZ zZ#>h|a>fHt=4mJiy?OObZ6j8`8bz?L28{2 zw?jE)-rUJk=AOM;r}^|8;JYqI*Z+LN$?fbzkl5X$ltsyf3BcYCtWMdHv^{aV?~eVu z_U_y-&9MQ@s@g$iq|>$<&YF(d2q6oj0kB)y(C~t={B60uI#4%?j0yP(YC21tkd&N| z!6z;?Xbnq3Q^JzN5~<{SpB&GQAwU;D7aGMQZ2-R`&61Xr&NZyxwPDBF#4vqW>NfgX zxDR65@rf!rQ<9LESY+hLz;MUbg3zK+-;i~|8$#AgK|X~5LkN-i*M)PyeIgfQ&ov|Y zKxE(5B-QHcQhlqzLP;5J54mbj=OuLx1%qt?^bw&`B{My_)@>-2gp*gR(Pz9{PZ%WcbGeJfMYUJa}R{xq( z!4Wm+0@+>hv3$}5nLGtwdB2d)!dJ|$Z2BieX4oF0#rORpS2BDwoUT1t*y&<5l|L z6PbO#Ve63PCayBPXnBxIzSa7(#u8(Wjs~D}bToL~v?1%ZN$GZW z!(kqL9+nsmT)E>$aPm%m1+I3V)#N2Ly7HrVueeoKd$91>F;#VDO?nmAaHRC?IaN1U zZ&vTC^W|P??H8 zt(!nK+>8$!$*cVzZrvGPA673t_b$aqj8zAT<+D#>a3p8$?kzvX?;}qU@g5?BC5kU9 zNte%;U|{64t-UaPaW-@T5p?cToA-<*J~B<&ohWw)w!cW5@;|KTS&P zdM@^C&=Jm7WvQuF;Sk3XkA)rN%thJ7MXHv_mUYKCt3-bAB$=I!*|QU!uBKhZbP#=E z{Sx{zpByqec&nOX;AWqEGK|~B`?q~EWY@agEBCD0xAy$>Ep+Iw{iNP-%OAfs{d|!=I z%ex;^FJ#^vx*H}$k2uZ0HJ)?}>4_CsabMZA&Jc#Ys@R)F(Rw9Lnly(JKiTo73>MNq zq;8P#^nSs+0)*yGh>sxm?VNs(q>+3~)5-AR<@jg7zvM1>+fC`5PU709ONw3o%D0y+ z7|mswByTJ^_0cCMPF%l!bkVeIUby+#Unxi=_cmXCea8A#Yhts;gSNn2s#9Pz3USvXoF>* z1qz5+X8?tr|2n`1gQ*WEI3#r%uqSZ+d-PuzdxCevO7{WvelUFa4`d{OX2>D4?1)DchD@fD zkx%dkAp|kmQ5vKI{Ml#3kIgO2u;~m?lEMpM-UP%pX}gRT#qSnQ+qz-D6$q_np!we% z#v?kG2bBWvH=AG#w*FfNQ__W`u+YjV21KEFU3k~oQ%RRJQ(xlui|RfS2y{pT?e^Yl zoa-{#q3lO}fkjxdhI{XB1CWzLfSViu(}yU&meJ<>;tZL)HC{G=GR2dFGCGgM(hcOp zc<#XBrr@#!>B(h9OJ=BM1i{H1Fk=7*NWK%0{1(am0WAXt1hurZ6dgNxgexm*+I8T# zlzdnWQp*O$sKYg~>3mgubySt5{$3Fhd@G5fmb|miIhNGRb505zc}JO(V|1k3puUlv zVK8KvQ|##wWHRMgrSb{-)fbf+_Ed`@!;qN;Vuv*?H#5f~&5~GivT_Y}>8uM%b55o; z-2&{m$(U)(uo!Ha)=Zn(Y?0OnDswC*yTN9#rXh)#k(r%lO}85C#+)1}!T?>BW?Q-) z$N&gO7?C!&r8$gJd2c<)gch?+dfA|~r&?1?TuPcDJ&%jV_J>m7EhjX#&CG}$0P zV@ffmr)Q^Sg970&18-w9*`%(;t~pG_3l3q!?yMtxnd!T?G&{m;R=oLg7VQ$ITGp7= z0HX<~kKqLViyF`ZX25vy#L&qLUWauretq((&qI0l`2SD>mMinB4LhRCn7V~eVN$Fu zP8}EPK`3b5+K*vxxV7R}@zhr)XmR%Is!M9}cy4h%WV1ykvRAQnh@pe{fv& z4*p=(dxuqWYvqlw>o-&+{ZrCN-X*Vc=MP?M_+-0u_wDcZ{HT^2{IRNumXT-n?|1B1 z=UB5$IlSCH!4a1o75#4VyDL-+@C;qngg&E|n?r_%!H$Fxa>!;Y#Q zJ9
      ","
      "],tr:[2,"","
      "],col:[2,"","
      "],td:[3,"","
      "],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
      ","
      "]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("'),$templateCache.put("/views/modals/choose-date-modal.html",''),$templateCache.put("/views/modals/confirm-trash-modal.html",''),$templateCache.put("/views/modals/login-modal.html",''),$templateCache.put("/views/modals/pubtime-validation-modal.html",''),$templateCache.put("/views/modals/send-to-editor-modal.html",''),$templateCache.put("/views/nav.html",''),$templateCache.put("/views/promotion-tool-article-container.html",'
      No image selected.

      ·

      '),$templateCache.put("/views/promotion.html",'

      Currently promoted

      '),$templateCache.put("/views/pzones.html",'

      Promotion Zone Editor

      '),$templateCache.put("/views/pzones/carousel.html","
      Looks like this P'Zone is outdated
      "),$templateCache.put("/views/pzones/feature_type.html","
      Coming soon!
      "),$templateCache.put("/views/pzones/list.html",'
      Content IDActions
      '),$templateCache.put("/views/pzones/oneup.html","
      Looks like this P'Zone is outdated
      "),$templateCache.put("/views/pzones/reviews.html",'

      The "reviews" promoted zone has no available options.

      '),$templateCache.put("/views/pzones/twoup.html","
      Looks like this P'Zone is outdated
      "),$templateCache.put("/views/rating.html",'
      '),$templateCache.put("/views/slideshow-pane.html",'
      ",support.noCloneChecked=!!div.cloneNode(!0).lastChild.defaultValue}();var strundefined="undefined";support.focusinBubbles="onfocusin"in window;var rkeyEvent=/^key/,rmouseEvent=/^(?:mouse|contextmenu)|click/,rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,rtypenamespace=/^([^.]*)(?:\.(.+)|)$/;jQuery.event={global:{},add:function(elem,types,handler,data,selector){var handleObjIn,eventHandle,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=data_priv.get(elem);if(elemData)for(handler.handler&&(handleObjIn=handler,handler=handleObjIn.handler,selector=handleObjIn.selector),handler.guid||(handler.guid=jQuery.guid++),(events=elemData.events)||(events=elemData.events={}),(eventHandle=elemData.handle)||(eventHandle=elemData.handle=function(e){return typeof jQuery!==strundefined&&jQuery.event.triggered!==e.type?jQuery.event.dispatch.apply(elem,arguments):void 0}),types=(types||"").match(rnotwhite)||[""],t=types.length;t--;)tmp=rtypenamespace.exec(types[t])||[],type=origType=tmp[1],namespaces=(tmp[2]||"").split(".").sort(),type&&(special=jQuery.event.special[type]||{},type=(selector?special.delegateType:special.bindType)||type,special=jQuery.event.special[type]||{},handleObj=jQuery.extend({type:type,origType:origType,data:data,handler:handler,guid:handler.guid,selector:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),namespace:namespaces.join(".")},handleObjIn),(handlers=events[type])||(handlers=events[type]=[],handlers.delegateCount=0,special.setup&&special.setup.call(elem,data,namespaces,eventHandle)!==!1||elem.addEventListener&&elem.addEventListener(type,eventHandle,!1)),special.add&&(special.add.call(elem,handleObj),handleObj.handler.guid||(handleObj.handler.guid=handler.guid)),selector?handlers.splice(handlers.delegateCount++,0,handleObj):handlers.push(handleObj),jQuery.event.global[type]=!0)},remove:function(elem,types,handler,selector,mappedTypes){var j,origCount,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=data_priv.hasData(elem)&&data_priv.get(elem);if(elemData&&(events=elemData.events)){for(types=(types||"").match(rnotwhite)||[""],t=types.length;t--;)if(tmp=rtypenamespace.exec(types[t])||[],type=origType=tmp[1],namespaces=(tmp[2]||"").split(".").sort(),type){for(special=jQuery.event.special[type]||{},type=(selector?special.delegateType:special.bindType)||type,handlers=events[type]||[],tmp=tmp[2]&&new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"),origCount=j=handlers.length;j--;)handleObj=handlers[j],!mappedTypes&&origType!==handleObj.origType||handler&&handler.guid!==handleObj.guid||tmp&&!tmp.test(handleObj.namespace)||selector&&selector!==handleObj.selector&&("**"!==selector||!handleObj.selector)||(handlers.splice(j,1),handleObj.selector&&handlers.delegateCount--,special.remove&&special.remove.call(elem,handleObj));origCount&&!handlers.length&&(special.teardown&&special.teardown.call(elem,namespaces,elemData.handle)!==!1||jQuery.removeEvent(elem,type,elemData.handle),delete events[type])}else for(type in events)jQuery.event.remove(elem,type+types[t],handler,selector,!0);jQuery.isEmptyObject(events)&&(delete elemData.handle,data_priv.remove(elem,"events"))}},trigger:function(event,data,elem,onlyHandlers){var i,cur,tmp,bubbleType,ontype,handle,special,eventPath=[elem||document],type=hasOwn.call(event,"type")?event.type:event,namespaces=hasOwn.call(event,"namespace")?event.namespace.split("."):[];if(cur=tmp=elem=elem||document,3!==elem.nodeType&&8!==elem.nodeType&&!rfocusMorph.test(type+jQuery.event.triggered)&&(type.indexOf(".")>=0&&(namespaces=type.split("."),type=namespaces.shift(),namespaces.sort()),ontype=type.indexOf(":")<0&&"on"+type,event=event[jQuery.expando]?event:new jQuery.Event(type,"object"==typeof event&&event),event.isTrigger=onlyHandlers?2:3,event.namespace=namespaces.join("."),event.namespace_re=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,event.result=void 0,event.target||(event.target=elem),data=null==data?[event]:jQuery.makeArray(data,[event]),special=jQuery.event.special[type]||{},onlyHandlers||!special.trigger||special.trigger.apply(elem,data)!==!1)){if(!onlyHandlers&&!special.noBubble&&!jQuery.isWindow(elem)){for(bubbleType=special.delegateType||type,rfocusMorph.test(bubbleType+type)||(cur=cur.parentNode);cur;cur=cur.parentNode)eventPath.push(cur),tmp=cur;tmp===(elem.ownerDocument||document)&&eventPath.push(tmp.defaultView||tmp.parentWindow||window)}for(i=0;(cur=eventPath[i++])&&!event.isPropagationStopped();)event.type=i>1?bubbleType:special.bindType||type,handle=(data_priv.get(cur,"events")||{})[event.type]&&data_priv.get(cur,"handle"),handle&&handle.apply(cur,data),handle=ontype&&cur[ontype],handle&&handle.apply&&jQuery.acceptData(cur)&&(event.result=handle.apply(cur,data),event.result===!1&&event.preventDefault());return event.type=type,onlyHandlers||event.isDefaultPrevented()||special._default&&special._default.apply(eventPath.pop(),data)!==!1||!jQuery.acceptData(elem)||ontype&&jQuery.isFunction(elem[type])&&!jQuery.isWindow(elem)&&(tmp=elem[ontype],tmp&&(elem[ontype]=null),jQuery.event.triggered=type,elem[type](),jQuery.event.triggered=void 0,tmp&&(elem[ontype]=tmp)),event.result}},dispatch:function(event){event=jQuery.event.fix(event);var i,j,ret,matched,handleObj,handlerQueue=[],args=slice.call(arguments),handlers=(data_priv.get(this,"events")||{})[event.type]||[],special=jQuery.event.special[event.type]||{};if(args[0]=event,event.delegateTarget=this,!special.preDispatch||special.preDispatch.call(this,event)!==!1){for(handlerQueue=jQuery.event.handlers.call(this,event,handlers),i=0;(matched=handlerQueue[i++])&&!event.isPropagationStopped();)for(event.currentTarget=matched.elem,j=0;(handleObj=matched.handlers[j++])&&!event.isImmediatePropagationStopped();)(!event.namespace_re||event.namespace_re.test(handleObj.namespace))&&(event.handleObj=handleObj,event.data=handleObj.data,ret=((jQuery.event.special[handleObj.origType]||{}).handle||handleObj.handler).apply(matched.elem,args),void 0!==ret&&(event.result=ret)===!1&&(event.preventDefault(),event.stopPropagation()));return special.postDispatch&&special.postDispatch.call(this,event),event.result}},handlers:function(event,handlers){var i,matches,sel,handleObj,handlerQueue=[],delegateCount=handlers.delegateCount,cur=event.target;if(delegateCount&&cur.nodeType&&(!event.button||"click"!==event.type))for(;cur!==this;cur=cur.parentNode||this)if(cur.disabled!==!0||"click"!==event.type){for(matches=[],i=0;delegateCount>i;i++)handleObj=handlers[i],sel=handleObj.selector+" ",void 0===matches[sel]&&(matches[sel]=handleObj.needsContext?jQuery(sel,this).index(cur)>=0:jQuery.find(sel,this,null,[cur]).length),matches[sel]&&matches.push(handleObj);matches.length&&handlerQueue.push({elem:cur,handlers:matches})}return delegateCount]*)\/>/gi,rtagName=/<([\w:]+)/,rhtml=/<|&#?\w+;/,rnoInnerhtml=/<(?:script|style|link)/i,rchecked=/checked\s*(?:[^=]|=\s*.checked.)/i,rscriptType=/^$|\/(?:java|ecma)script/i,rscriptTypeMasked=/^true\/(.*)/,rcleanScript=/^\s*\s*$/g,wrapMap={option:[1,""],thead:[1,"","
      "],col:[2,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],_default:[0,"",""]};wrapMap.optgroup=wrapMap.option,wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead,wrapMap.th=wrapMap.td,jQuery.extend({clone:function(elem,dataAndEvents,deepDataAndEvents){var i,l,srcElements,destElements,clone=elem.cloneNode(!0),inPage=jQuery.contains(elem.ownerDocument,elem);if(!(support.noCloneChecked||1!==elem.nodeType&&11!==elem.nodeType||jQuery.isXMLDoc(elem)))for(destElements=getAll(clone),srcElements=getAll(elem),i=0,l=srcElements.length;l>i;i++)fixInput(srcElements[i],destElements[i]);if(dataAndEvents)if(deepDataAndEvents)for(srcElements=srcElements||getAll(elem),destElements=destElements||getAll(clone),i=0,l=srcElements.length;l>i;i++)cloneCopyEvent(srcElements[i],destElements[i]);else cloneCopyEvent(elem,clone);return destElements=getAll(clone,"script"),destElements.length>0&&setGlobalEval(destElements,!inPage&&getAll(elem,"script")),clone},buildFragment:function(elems,context,scripts,selection){for(var elem,tmp,tag,wrap,contains,j,fragment=context.createDocumentFragment(),nodes=[],i=0,l=elems.length;l>i;i++)if(elem=elems[i],elem||0===elem)if("object"===jQuery.type(elem))jQuery.merge(nodes,elem.nodeType?[elem]:elem);else if(rhtml.test(elem)){for(tmp=tmp||fragment.appendChild(context.createElement("div")),tag=(rtagName.exec(elem)||["",""])[1].toLowerCase(),wrap=wrapMap[tag]||wrapMap._default,tmp.innerHTML=wrap[1]+elem.replace(rxhtmlTag,"<$1>")+wrap[2],j=wrap[0];j--;)tmp=tmp.lastChild;jQuery.merge(nodes,tmp.childNodes),tmp=fragment.firstChild,tmp.textContent=""}else nodes.push(context.createTextNode(elem));for(fragment.textContent="",i=0;elem=nodes[i++];)if((!selection||-1===jQuery.inArray(elem,selection))&&(contains=jQuery.contains(elem.ownerDocument,elem),tmp=getAll(fragment.appendChild(elem),"script"),contains&&setGlobalEval(tmp),scripts))for(j=0;elem=tmp[j++];)rscriptType.test(elem.type||"")&&scripts.push(elem);return fragment},cleanData:function(elems){for(var data,elem,events,type,key,j,special=jQuery.event.special,i=0;void 0!==(elem=elems[i]);i++){if(jQuery.acceptData(elem)&&(key=elem[data_priv.expando],key&&(data=data_priv.cache[key]))){if(events=Object.keys(data.events||{}),events.length)for(j=0;void 0!==(type=events[j]);j++)special[type]?jQuery.event.remove(elem,type):jQuery.removeEvent(elem,type,data.handle);data_priv.cache[key]&&delete data_priv.cache[key]}delete data_user.cache[elem[data_user.expando]]}}}),jQuery.fn.extend({text:function(value){return access(this,function(value){return void 0===value?jQuery.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=value)})},null,value,arguments.length)},append:function(){return this.domManip(arguments,function(elem){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var target=manipulationTarget(this,elem);target.appendChild(elem)}})},prepend:function(){return this.domManip(arguments,function(elem){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var target=manipulationTarget(this,elem);target.insertBefore(elem,target.firstChild)}})},before:function(){return this.domManip(arguments,function(elem){this.parentNode&&this.parentNode.insertBefore(elem,this)})},after:function(){return this.domManip(arguments,function(elem){this.parentNode&&this.parentNode.insertBefore(elem,this.nextSibling)})},remove:function(selector,keepData){for(var elem,elems=selector?jQuery.filter(selector,this):this,i=0;null!=(elem=elems[i]);i++)keepData||1!==elem.nodeType||jQuery.cleanData(getAll(elem)),elem.parentNode&&(keepData&&jQuery.contains(elem.ownerDocument,elem)&&setGlobalEval(getAll(elem,"script")),elem.parentNode.removeChild(elem));return this},empty:function(){for(var elem,i=0;null!=(elem=this[i]);i++)1===elem.nodeType&&(jQuery.cleanData(getAll(elem,!1)),elem.textContent="");return this},clone:function(dataAndEvents,deepDataAndEvents){return dataAndEvents=null==dataAndEvents?!1:dataAndEvents,deepDataAndEvents=null==deepDataAndEvents?dataAndEvents:deepDataAndEvents,this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents)})},html:function(value){return access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(void 0===value&&1===elem.nodeType)return elem.innerHTML;if("string"==typeof value&&!rnoInnerhtml.test(value)&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=value.replace(rxhtmlTag,"<$1>");try{for(;l>i;i++)elem=this[i]||{},1===elem.nodeType&&(jQuery.cleanData(getAll(elem,!1)),elem.innerHTML=value);elem=0}catch(e){}}elem&&this.empty().append(value)},null,value,arguments.length)},replaceWith:function(){var arg=arguments[0];return this.domManip(arguments,function(elem){arg=this.parentNode,jQuery.cleanData(getAll(this)),arg&&arg.replaceChild(elem,this)}),arg&&(arg.length||arg.nodeType)?this:this.remove()},detach:function(selector){return this.remove(selector,!0)},domManip:function(args,callback){args=concat.apply([],args);var fragment,first,scripts,hasScripts,node,doc,i=0,l=this.length,set=this,iNoClone=l-1,value=args[0],isFunction=jQuery.isFunction(value);if(isFunction||l>1&&"string"==typeof value&&!support.checkClone&&rchecked.test(value))return this.each(function(index){var self=set.eq(index);isFunction&&(args[0]=value.call(this,index,self.html())),self.domManip(args,callback)});if(l&&(fragment=jQuery.buildFragment(args,this[0].ownerDocument,!1,this),first=fragment.firstChild,1===fragment.childNodes.length&&(fragment=first),first)){for(scripts=jQuery.map(getAll(fragment,"script"),disableScript),hasScripts=scripts.length;l>i;i++)node=fragment,i!==iNoClone&&(node=jQuery.clone(node,!0,!0),hasScripts&&jQuery.merge(scripts,getAll(node,"script"))),callback.call(this[i],node,i);if(hasScripts)for(doc=scripts[scripts.length-1].ownerDocument,jQuery.map(scripts,restoreScript),i=0;hasScripts>i;i++)node=scripts[i],rscriptType.test(node.type||"")&&!data_priv.access(node,"globalEval")&&jQuery.contains(doc,node)&&(node.src?jQuery._evalUrl&&jQuery._evalUrl(node.src):jQuery.globalEval(node.textContent.replace(rcleanScript,"")))}return this}}),jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(selector){for(var elems,ret=[],insert=jQuery(selector),last=insert.length-1,i=0;last>=i;i++)elems=i===last?this:this.clone(!0),jQuery(insert[i])[original](elems),push.apply(ret,elems.get());return this.pushStack(ret)}});var iframe,elemdisplay={},rmargin=/^margin/,rnumnonpx=new RegExp("^("+pnum+")(?!px)[a-z%]+$","i"),getStyles=function(elem){return elem.ownerDocument.defaultView.getComputedStyle(elem,null)};!function(){function computePixelPositionAndBoxSizingReliable(){div.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",docElem.appendChild(container);var divStyle=window.getComputedStyle(div,null);pixelPositionVal="1%"!==divStyle.top,boxSizingReliableVal="4px"===divStyle.width,docElem.removeChild(container)}var pixelPositionVal,boxSizingReliableVal,divReset="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",docElem=document.documentElement,container=document.createElement("div"),div=document.createElement("div");div.style.backgroundClip="content-box",div.cloneNode(!0).style.backgroundClip="",support.clearCloneStyle="content-box"===div.style.backgroundClip,container.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",container.appendChild(div),window.getComputedStyle&&jQuery.extend(support,{pixelPosition:function(){return computePixelPositionAndBoxSizingReliable(),pixelPositionVal},boxSizingReliable:function(){return null==boxSizingReliableVal&&computePixelPositionAndBoxSizingReliable(),boxSizingReliableVal},reliableMarginRight:function(){var ret,marginDiv=div.appendChild(document.createElement("div"));return marginDiv.style.cssText=div.style.cssText=divReset,marginDiv.style.marginRight=marginDiv.style.width="0",div.style.width="1px",docElem.appendChild(container),ret=!parseFloat(window.getComputedStyle(marginDiv,null).marginRight),docElem.removeChild(container),div.innerHTML="",ret}})}(),jQuery.swap=function(elem,options,callback,args){var ret,name,old={};for(name in options)old[name]=elem.style[name],elem.style[name]=options[name];ret=callback.apply(elem,args||[]);for(name in options)elem.style[name]=old[name];return ret};var rdisplayswap=/^(none|table(?!-c[ea]).+)/,rnumsplit=new RegExp("^("+pnum+")(.*)$","i"),rrelNum=new RegExp("^([+-])=("+pnum+")","i"),cssShow={position:"absolute",visibility:"hidden",display:"block"},cssNormalTransform={letterSpacing:0,fontWeight:400},cssPrefixes=["Webkit","O","Moz","ms"];jQuery.extend({cssHooks:{opacity:{get:function(elem,computed){if(computed){var ret=curCSS(elem,"opacity");return""===ret?"1":ret}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(elem,name,value,extra){if(elem&&3!==elem.nodeType&&8!==elem.nodeType&&elem.style){var ret,type,hooks,origName=jQuery.camelCase(name),style=elem.style;return name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(style,origName)),hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName],void 0===value?hooks&&"get"in hooks&&void 0!==(ret=hooks.get(elem,!1,extra))?ret:style[name]:(type=typeof value,"string"===type&&(ret=rrelNum.exec(value))&&(value=(ret[1]+1)*ret[2]+parseFloat(jQuery.css(elem,name)),type="number"),null!=value&&value===value&&("number"!==type||jQuery.cssNumber[origName]||(value+="px"),support.clearCloneStyle||""!==value||0!==name.indexOf("background")||(style[name]="inherit"),hooks&&"set"in hooks&&void 0===(value=hooks.set(elem,value,extra))||(style[name]="",style[name]=value)),void 0)}},css:function(elem,name,extra,styles){var val,num,hooks,origName=jQuery.camelCase(name);return name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(elem.style,origName)),hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName],hooks&&"get"in hooks&&(val=hooks.get(elem,!0,extra)),void 0===val&&(val=curCSS(elem,name,styles)),"normal"===val&&name in cssNormalTransform&&(val=cssNormalTransform[name]),""===extra||extra?(num=parseFloat(val),extra===!0||jQuery.isNumeric(num)?num||0:val):val}}),jQuery.each(["height","width"],function(i,name){jQuery.cssHooks[name]={get:function(elem,computed,extra){return computed?0===elem.offsetWidth&&rdisplayswap.test(jQuery.css(elem,"display"))?jQuery.swap(elem,cssShow,function(){return getWidthOrHeight(elem,name,extra)}):getWidthOrHeight(elem,name,extra):void 0},set:function(elem,value,extra){var styles=extra&&getStyles(elem);return setPositiveNumber(elem,value,extra?augmentWidthOrHeight(elem,name,extra,"border-box"===jQuery.css(elem,"boxSizing",!1,styles),styles):0)}}}),jQuery.cssHooks.marginRight=addGetHookIf(support.reliableMarginRight,function(elem,computed){return computed?jQuery.swap(elem,{display:"inline-block"},curCSS,[elem,"marginRight"]):void 0}),jQuery.each({margin:"",padding:"",border:"Width"},function(prefix,suffix){jQuery.cssHooks[prefix+suffix]={expand:function(value){for(var i=0,expanded={},parts="string"==typeof value?value.split(" "):[value];4>i;i++)expanded[prefix+cssExpand[i]+suffix]=parts[i]||parts[i-2]||parts[0];return expanded}},rmargin.test(prefix)||(jQuery.cssHooks[prefix+suffix].set=setPositiveNumber)}),jQuery.fn.extend({css:function(name,value){return access(this,function(elem,name,value){var styles,len,map={},i=0;if(jQuery.isArray(name)){for(styles=getStyles(elem),len=name.length;len>i;i++)map[name[i]]=jQuery.css(elem,name[i],!1,styles);return map}return void 0!==value?jQuery.style(elem,name,value):jQuery.css(elem,name)},name,value,arguments.length>1)},show:function(){return showHide(this,!0)},hide:function(){return showHide(this)},toggle:function(state){return"boolean"==typeof state?state?this.show():this.hide():this.each(function(){isHidden(this)?jQuery(this).show():jQuery(this).hide()})}}),jQuery.Tween=Tween,Tween.prototype={constructor:Tween,init:function(elem,options,prop,end,easing,unit){this.elem=elem,this.prop=prop,this.easing=easing||"swing",this.options=options,this.start=this.now=this.cur(),this.end=end,this.unit=unit||(jQuery.cssNumber[prop]?"":"px")},cur:function(){var hooks=Tween.propHooks[this.prop];return hooks&&hooks.get?hooks.get(this):Tween.propHooks._default.get(this)},run:function(percent){var eased,hooks=Tween.propHooks[this.prop];return this.pos=eased=this.options.duration?jQuery.easing[this.easing](percent,this.options.duration*percent,0,1,this.options.duration):percent,this.now=(this.end-this.start)*eased+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),hooks&&hooks.set?hooks.set(this):Tween.propHooks._default.set(this),this}},Tween.prototype.init.prototype=Tween.prototype,Tween.propHooks={_default:{get:function(tween){var result;return null==tween.elem[tween.prop]||tween.elem.style&&null!=tween.elem.style[tween.prop]?(result=jQuery.css(tween.elem,tween.prop,""),result&&"auto"!==result?result:0):tween.elem[tween.prop]},set:function(tween){jQuery.fx.step[tween.prop]?jQuery.fx.step[tween.prop](tween):tween.elem.style&&(null!=tween.elem.style[jQuery.cssProps[tween.prop]]||jQuery.cssHooks[tween.prop])?jQuery.style(tween.elem,tween.prop,tween.now+tween.unit):tween.elem[tween.prop]=tween.now}}},Tween.propHooks.scrollTop=Tween.propHooks.scrollLeft={set:function(tween){tween.elem.nodeType&&tween.elem.parentNode&&(tween.elem[tween.prop]=tween.now)}},jQuery.easing={linear:function(p){return p},swing:function(p){return.5-Math.cos(p*Math.PI)/2}},jQuery.fx=Tween.prototype.init,jQuery.fx.step={};var fxNow,timerId,rfxtypes=/^(?:toggle|show|hide)$/,rfxnum=new RegExp("^(?:([+-])=|)("+pnum+")([a-z%]*)$","i"),rrun=/queueHooks$/,animationPrefilters=[defaultPrefilter],tweeners={"*":[function(prop,value){var tween=this.createTween(prop,value),target=tween.cur(),parts=rfxnum.exec(value),unit=parts&&parts[3]||(jQuery.cssNumber[prop]?"":"px"),start=(jQuery.cssNumber[prop]||"px"!==unit&&+target)&&rfxnum.exec(jQuery.css(tween.elem,prop)),scale=1,maxIterations=20;if(start&&start[3]!==unit){unit=unit||start[3],parts=parts||[],start=+target||1;do scale=scale||".5",start/=scale,jQuery.style(tween.elem,prop,start+unit);while(scale!==(scale=tween.cur()/target)&&1!==scale&&--maxIterations)}return parts&&(start=tween.start=+start||+target||0,tween.unit=unit,tween.end=parts[1]?start+(parts[1]+1)*parts[2]:+parts[2]),tween}]};jQuery.Animation=jQuery.extend(Animation,{tweener:function(props,callback){jQuery.isFunction(props)?(callback=props,props=["*"]):props=props.split(" ");for(var prop,index=0,length=props.length;length>index;index++)prop=props[index],tweeners[prop]=tweeners[prop]||[],tweeners[prop].unshift(callback)},prefilter:function(callback,prepend){prepend?animationPrefilters.unshift(callback):animationPrefilters.push(callback)}}),jQuery.speed=function(speed,easing,fn){var opt=speed&&"object"==typeof speed?jQuery.extend({},speed):{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&!jQuery.isFunction(easing)&&easing};return opt.duration=jQuery.fx.off?0:"number"==typeof opt.duration?opt.duration:opt.duration in jQuery.fx.speeds?jQuery.fx.speeds[opt.duration]:jQuery.fx.speeds._default,(null==opt.queue||opt.queue===!0)&&(opt.queue="fx"),opt.old=opt.complete,opt.complete=function(){jQuery.isFunction(opt.old)&&opt.old.call(this),opt.queue&&jQuery.dequeue(this,opt.queue) +},opt},jQuery.fn.extend({fadeTo:function(speed,to,easing,callback){return this.filter(isHidden).css("opacity",0).show().end().animate({opacity:to},speed,easing,callback)},animate:function(prop,speed,easing,callback){var empty=jQuery.isEmptyObject(prop),optall=jQuery.speed(speed,easing,callback),doAnimation=function(){var anim=Animation(this,jQuery.extend({},prop),optall);(empty||data_priv.get(this,"finish"))&&anim.stop(!0)};return doAnimation.finish=doAnimation,empty||optall.queue===!1?this.each(doAnimation):this.queue(optall.queue,doAnimation)},stop:function(type,clearQueue,gotoEnd){var stopQueue=function(hooks){var stop=hooks.stop;delete hooks.stop,stop(gotoEnd)};return"string"!=typeof type&&(gotoEnd=clearQueue,clearQueue=type,type=void 0),clearQueue&&type!==!1&&this.queue(type||"fx",[]),this.each(function(){var dequeue=!0,index=null!=type&&type+"queueHooks",timers=jQuery.timers,data=data_priv.get(this);if(index)data[index]&&data[index].stop&&stopQueue(data[index]);else for(index in data)data[index]&&data[index].stop&&rrun.test(index)&&stopQueue(data[index]);for(index=timers.length;index--;)timers[index].elem!==this||null!=type&&timers[index].queue!==type||(timers[index].anim.stop(gotoEnd),dequeue=!1,timers.splice(index,1));(dequeue||!gotoEnd)&&jQuery.dequeue(this,type)})},finish:function(type){return type!==!1&&(type=type||"fx"),this.each(function(){var index,data=data_priv.get(this),queue=data[type+"queue"],hooks=data[type+"queueHooks"],timers=jQuery.timers,length=queue?queue.length:0;for(data.finish=!0,jQuery.queue(this,type,[]),hooks&&hooks.stop&&hooks.stop.call(this,!0),index=timers.length;index--;)timers[index].elem===this&&timers[index].queue===type&&(timers[index].anim.stop(!0),timers.splice(index,1));for(index=0;length>index;index++)queue[index]&&queue[index].finish&&queue[index].finish.call(this);delete data.finish})}}),jQuery.each(["toggle","show","hide"],function(i,name){var cssFn=jQuery.fn[name];jQuery.fn[name]=function(speed,easing,callback){return null==speed||"boolean"==typeof speed?cssFn.apply(this,arguments):this.animate(genFx(name,!0),speed,easing,callback)}}),jQuery.each({slideDown:genFx("show"),slideUp:genFx("hide"),slideToggle:genFx("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(name,props){jQuery.fn[name]=function(speed,easing,callback){return this.animate(props,speed,easing,callback)}}),jQuery.timers=[],jQuery.fx.tick=function(){var timer,i=0,timers=jQuery.timers;for(fxNow=jQuery.now();i1)},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name)})}}),jQuery.extend({attr:function(elem,name,value){var hooks,ret,nType=elem.nodeType;if(elem&&3!==nType&&8!==nType&&2!==nType)return typeof elem.getAttribute===strundefined?jQuery.prop(elem,name,value):(1===nType&&jQuery.isXMLDoc(elem)||(name=name.toLowerCase(),hooks=jQuery.attrHooks[name]||(jQuery.expr.match.bool.test(name)?boolHook:nodeHook)),void 0===value?hooks&&"get"in hooks&&null!==(ret=hooks.get(elem,name))?ret:(ret=jQuery.find.attr(elem,name),null==ret?void 0:ret):null!==value?hooks&&"set"in hooks&&void 0!==(ret=hooks.set(elem,value,name))?ret:(elem.setAttribute(name,value+""),value):void jQuery.removeAttr(elem,name))},removeAttr:function(elem,value){var name,propName,i=0,attrNames=value&&value.match(rnotwhite);if(attrNames&&1===elem.nodeType)for(;name=attrNames[i++];)propName=jQuery.propFix[name]||name,jQuery.expr.match.bool.test(name)&&(elem[propName]=!1),elem.removeAttribute(name)},attrHooks:{type:{set:function(elem,value){if(!support.radioValue&&"radio"===value&&jQuery.nodeName(elem,"input")){var val=elem.value;return elem.setAttribute("type",value),val&&(elem.value=val),value}}}}}),boolHook={set:function(elem,value,name){return value===!1?jQuery.removeAttr(elem,name):elem.setAttribute(name,name),name}},jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g),function(i,name){var getter=attrHandle[name]||jQuery.find.attr;attrHandle[name]=function(elem,name,isXML){var ret,handle;return isXML||(handle=attrHandle[name],attrHandle[name]=ret,ret=null!=getter(elem,name,isXML)?name.toLowerCase():null,attrHandle[name]=handle),ret}});var rfocusable=/^(?:input|select|textarea|button)$/i;jQuery.fn.extend({prop:function(name,value){return access(this,jQuery.prop,name,value,arguments.length>1)},removeProp:function(name){return this.each(function(){delete this[jQuery.propFix[name]||name]})}}),jQuery.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(elem,name,value){var ret,hooks,notxml,nType=elem.nodeType;if(elem&&3!==nType&&8!==nType&&2!==nType)return notxml=1!==nType||!jQuery.isXMLDoc(elem),notxml&&(name=jQuery.propFix[name]||name,hooks=jQuery.propHooks[name]),void 0!==value?hooks&&"set"in hooks&&void 0!==(ret=hooks.set(elem,value,name))?ret:elem[name]=value:hooks&&"get"in hooks&&null!==(ret=hooks.get(elem,name))?ret:elem[name]},propHooks:{tabIndex:{get:function(elem){return elem.hasAttribute("tabindex")||rfocusable.test(elem.nodeName)||elem.href?elem.tabIndex:-1}}}}),support.optSelected||(jQuery.propHooks.selected={get:function(elem){var parent=elem.parentNode;return parent&&parent.parentNode&&parent.parentNode.selectedIndex,null}}),jQuery.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){jQuery.propFix[this.toLowerCase()]=this});var rclass=/[\t\r\n\f]/g;jQuery.fn.extend({addClass:function(value){var classes,elem,cur,clazz,j,finalValue,proceed="string"==typeof value&&value,i=0,len=this.length;if(jQuery.isFunction(value))return this.each(function(j){jQuery(this).addClass(value.call(this,j,this.className))});if(proceed)for(classes=(value||"").match(rnotwhite)||[];len>i;i++)if(elem=this[i],cur=1===elem.nodeType&&(elem.className?(" "+elem.className+" ").replace(rclass," "):" ")){for(j=0;clazz=classes[j++];)cur.indexOf(" "+clazz+" ")<0&&(cur+=clazz+" ");finalValue=jQuery.trim(cur),elem.className!==finalValue&&(elem.className=finalValue)}return this},removeClass:function(value){var classes,elem,cur,clazz,j,finalValue,proceed=0===arguments.length||"string"==typeof value&&value,i=0,len=this.length;if(jQuery.isFunction(value))return this.each(function(j){jQuery(this).removeClass(value.call(this,j,this.className))});if(proceed)for(classes=(value||"").match(rnotwhite)||[];len>i;i++)if(elem=this[i],cur=1===elem.nodeType&&(elem.className?(" "+elem.className+" ").replace(rclass," "):"")){for(j=0;clazz=classes[j++];)for(;cur.indexOf(" "+clazz+" ")>=0;)cur=cur.replace(" "+clazz+" "," ");finalValue=value?jQuery.trim(cur):"",elem.className!==finalValue&&(elem.className=finalValue)}return this},toggleClass:function(value,stateVal){var type=typeof value;return"boolean"==typeof stateVal&&"string"===type?stateVal?this.addClass(value):this.removeClass(value):this.each(jQuery.isFunction(value)?function(i){jQuery(this).toggleClass(value.call(this,i,this.className,stateVal),stateVal)}:function(){if("string"===type)for(var className,i=0,self=jQuery(this),classNames=value.match(rnotwhite)||[];className=classNames[i++];)self.hasClass(className)?self.removeClass(className):self.addClass(className);else(type===strundefined||"boolean"===type)&&(this.className&&data_priv.set(this,"__className__",this.className),this.className=this.className||value===!1?"":data_priv.get(this,"__className__")||"")})},hasClass:function(selector){for(var className=" "+selector+" ",i=0,l=this.length;l>i;i++)if(1===this[i].nodeType&&(" "+this[i].className+" ").replace(rclass," ").indexOf(className)>=0)return!0;return!1}});var rreturn=/\r/g;jQuery.fn.extend({val:function(value){var hooks,ret,isFunction,elem=this[0];{if(arguments.length)return isFunction=jQuery.isFunction(value),this.each(function(i){var val;1===this.nodeType&&(val=isFunction?value.call(this,i,jQuery(this).val()):value,null==val?val="":"number"==typeof val?val+="":jQuery.isArray(val)&&(val=jQuery.map(val,function(value){return null==value?"":value+""})),hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()],hooks&&"set"in hooks&&void 0!==hooks.set(this,val,"value")||(this.value=val))});if(elem)return hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()],hooks&&"get"in hooks&&void 0!==(ret=hooks.get(elem,"value"))?ret:(ret=elem.value,"string"==typeof ret?ret.replace(rreturn,""):null==ret?"":ret)}}}),jQuery.extend({valHooks:{select:{get:function(elem){for(var value,option,options=elem.options,index=elem.selectedIndex,one="select-one"===elem.type||0>index,values=one?null:[],max=one?index+1:options.length,i=0>index?max:one?index:0;max>i;i++)if(option=options[i],!(!option.selected&&i!==index||(support.optDisabled?option.disabled:null!==option.getAttribute("disabled"))||option.parentNode.disabled&&jQuery.nodeName(option.parentNode,"optgroup"))){if(value=jQuery(option).val(),one)return value;values.push(value)}return values},set:function(elem,value){for(var optionSet,option,options=elem.options,values=jQuery.makeArray(value),i=options.length;i--;)option=options[i],(option.selected=jQuery.inArray(jQuery(option).val(),values)>=0)&&(optionSet=!0);return optionSet||(elem.selectedIndex=-1),values}}}}),jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]={set:function(elem,value){return jQuery.isArray(value)?elem.checked=jQuery.inArray(jQuery(elem).val(),value)>=0:void 0}},support.checkOn||(jQuery.valHooks[this].get=function(elem){return null===elem.getAttribute("value")?"on":elem.value})}),jQuery.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(i,name){jQuery.fn[name]=function(data,fn){return arguments.length>0?this.on(name,null,data,fn):this.trigger(name)}}),jQuery.fn.extend({hover:function(fnOver,fnOut){return this.mouseenter(fnOver).mouseleave(fnOut||fnOver)},bind:function(types,data,fn){return this.on(types,null,data,fn)},unbind:function(types,fn){return this.off(types,null,fn)},delegate:function(selector,types,data,fn){return this.on(types,selector,data,fn)},undelegate:function(selector,types,fn){return 1===arguments.length?this.off(selector,"**"):this.off(types,selector||"**",fn)}});var nonce=jQuery.now(),rquery=/\?/;jQuery.parseJSON=function(data){return JSON.parse(data+"")},jQuery.parseXML=function(data){var xml,tmp;if(!data||"string"!=typeof data)return null;try{tmp=new DOMParser,xml=tmp.parseFromString(data,"text/xml")}catch(e){xml=void 0}return(!xml||xml.getElementsByTagName("parsererror").length)&&jQuery.error("Invalid XML: "+data),xml};var ajaxLocParts,ajaxLocation,rhash=/#.*$/,rts=/([?&])_=[^&]*/,rheaders=/^(.*?):[ \t]*([^\r\n]*)$/gm,rlocalProtocol=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,rnoContent=/^(?:GET|HEAD)$/,rprotocol=/^\/\//,rurl=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,prefilters={},transports={},allTypes="*/".concat("*");try{ajaxLocation=location.href}catch(e){ajaxLocation=document.createElement("a"),ajaxLocation.href="",ajaxLocation=ajaxLocation.href}ajaxLocParts=rurl.exec(ajaxLocation.toLowerCase())||[],jQuery.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ajaxLocation,type:"GET",isLocal:rlocalProtocol.test(ajaxLocParts[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":allTypes,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":jQuery.parseJSON,"text xml":jQuery.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(target,settings){return settings?ajaxExtend(ajaxExtend(target,jQuery.ajaxSettings),settings):ajaxExtend(jQuery.ajaxSettings,target)},ajaxPrefilter:addToPrefiltersOrTransports(prefilters),ajaxTransport:addToPrefiltersOrTransports(transports),ajax:function(url,options){function done(status,nativeStatusText,responses,headers){var isSuccess,success,error,response,modified,statusText=nativeStatusText;2!==state&&(state=2,timeoutTimer&&clearTimeout(timeoutTimer),transport=void 0,responseHeadersString=headers||"",jqXHR.readyState=status>0?4:0,isSuccess=status>=200&&300>status||304===status,responses&&(response=ajaxHandleResponses(s,jqXHR,responses)),response=ajaxConvert(s,response,jqXHR,isSuccess),isSuccess?(s.ifModified&&(modified=jqXHR.getResponseHeader("Last-Modified"),modified&&(jQuery.lastModified[cacheURL]=modified),modified=jqXHR.getResponseHeader("etag"),modified&&(jQuery.etag[cacheURL]=modified)),204===status||"HEAD"===s.type?statusText="nocontent":304===status?statusText="notmodified":(statusText=response.state,success=response.data,error=response.error,isSuccess=!error)):(error=statusText,(status||!statusText)&&(statusText="error",0>status&&(status=0))),jqXHR.status=status,jqXHR.statusText=(nativeStatusText||statusText)+"",isSuccess?deferred.resolveWith(callbackContext,[success,statusText,jqXHR]):deferred.rejectWith(callbackContext,[jqXHR,statusText,error]),jqXHR.statusCode(statusCode),statusCode=void 0,fireGlobals&&globalEventContext.trigger(isSuccess?"ajaxSuccess":"ajaxError",[jqXHR,s,isSuccess?success:error]),completeDeferred.fireWith(callbackContext,[jqXHR,statusText]),fireGlobals&&(globalEventContext.trigger("ajaxComplete",[jqXHR,s]),--jQuery.active||jQuery.event.trigger("ajaxStop")))}"object"==typeof url&&(options=url,url=void 0),options=options||{};var transport,cacheURL,responseHeadersString,responseHeaders,timeoutTimer,parts,fireGlobals,i,s=jQuery.ajaxSetup({},options),callbackContext=s.context||s,globalEventContext=s.context&&(callbackContext.nodeType||callbackContext.jquery)?jQuery(callbackContext):jQuery.event,deferred=jQuery.Deferred(),completeDeferred=jQuery.Callbacks("once memory"),statusCode=s.statusCode||{},requestHeaders={},requestHeadersNames={},state=0,strAbort="canceled",jqXHR={readyState:0,getResponseHeader:function(key){var match;if(2===state){if(!responseHeaders)for(responseHeaders={};match=rheaders.exec(responseHeadersString);)responseHeaders[match[1].toLowerCase()]=match[2];match=responseHeaders[key.toLowerCase()]}return null==match?null:match},getAllResponseHeaders:function(){return 2===state?responseHeadersString:null},setRequestHeader:function(name,value){var lname=name.toLowerCase();return state||(name=requestHeadersNames[lname]=requestHeadersNames[lname]||name,requestHeaders[name]=value),this},overrideMimeType:function(type){return state||(s.mimeType=type),this},statusCode:function(map){var code;if(map)if(2>state)for(code in map)statusCode[code]=[statusCode[code],map[code]];else jqXHR.always(map[jqXHR.status]);return this},abort:function(statusText){var finalText=statusText||strAbort;return transport&&transport.abort(finalText),done(0,finalText),this}};if(deferred.promise(jqXHR).complete=completeDeferred.add,jqXHR.success=jqXHR.done,jqXHR.error=jqXHR.fail,s.url=((url||s.url||ajaxLocation)+"").replace(rhash,"").replace(rprotocol,ajaxLocParts[1]+"//"),s.type=options.method||options.type||s.method||s.type,s.dataTypes=jQuery.trim(s.dataType||"*").toLowerCase().match(rnotwhite)||[""],null==s.crossDomain&&(parts=rurl.exec(s.url.toLowerCase()),s.crossDomain=!(!parts||parts[1]===ajaxLocParts[1]&&parts[2]===ajaxLocParts[2]&&(parts[3]||("http:"===parts[1]?"80":"443"))===(ajaxLocParts[3]||("http:"===ajaxLocParts[1]?"80":"443")))),s.data&&s.processData&&"string"!=typeof s.data&&(s.data=jQuery.param(s.data,s.traditional)),inspectPrefiltersOrTransports(prefilters,s,options,jqXHR),2===state)return jqXHR;fireGlobals=s.global,fireGlobals&&0===jQuery.active++&&jQuery.event.trigger("ajaxStart"),s.type=s.type.toUpperCase(),s.hasContent=!rnoContent.test(s.type),cacheURL=s.url,s.hasContent||(s.data&&(cacheURL=s.url+=(rquery.test(cacheURL)?"&":"?")+s.data,delete s.data),s.cache===!1&&(s.url=rts.test(cacheURL)?cacheURL.replace(rts,"$1_="+nonce++):cacheURL+(rquery.test(cacheURL)?"&":"?")+"_="+nonce++)),s.ifModified&&(jQuery.lastModified[cacheURL]&&jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[cacheURL]),jQuery.etag[cacheURL]&&jqXHR.setRequestHeader("If-None-Match",jQuery.etag[cacheURL])),(s.data&&s.hasContent&&s.contentType!==!1||options.contentType)&&jqXHR.setRequestHeader("Content-Type",s.contentType),jqXHR.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+("*"!==s.dataTypes[0]?", "+allTypes+"; q=0.01":""):s.accepts["*"]);for(i in s.headers)jqXHR.setRequestHeader(i,s.headers[i]);if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===!1||2===state))return jqXHR.abort();strAbort="abort";for(i in{success:1,error:1,complete:1})jqXHR[i](s[i]);if(transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR)){jqXHR.readyState=1,fireGlobals&&globalEventContext.trigger("ajaxSend",[jqXHR,s]),s.async&&s.timeout>0&&(timeoutTimer=setTimeout(function(){jqXHR.abort("timeout")},s.timeout));try{state=1,transport.send(requestHeaders,done)}catch(e){if(!(2>state))throw e;done(-1,e)}}else done(-1,"No Transport");return jqXHR},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json")},getScript:function(url,callback){return jQuery.get(url,void 0,callback,"script")}}),jQuery.each(["get","post"],function(i,method){jQuery[method]=function(url,data,callback,type){return jQuery.isFunction(data)&&(type=type||callback,callback=data,data=void 0),jQuery.ajax({url:url,type:method,dataType:type,data:data,success:callback})}}),jQuery.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(i,type){jQuery.fn[type]=function(fn){return this.on(type,fn)}}),jQuery._evalUrl=function(url){return jQuery.ajax({url:url,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},jQuery.fn.extend({wrapAll:function(html){var wrap;return jQuery.isFunction(html)?this.each(function(i){jQuery(this).wrapAll(html.call(this,i))}):(this[0]&&(wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&wrap.insertBefore(this[0]),wrap.map(function(){for(var elem=this;elem.firstElementChild;)elem=elem.firstElementChild;return elem}).append(this)),this)},wrapInner:function(html){return this.each(jQuery.isFunction(html)?function(i){jQuery(this).wrapInner(html.call(this,i))}:function(){var self=jQuery(this),contents=self.contents();contents.length?contents.wrapAll(html):self.append(html)})},wrap:function(html){var isFunction=jQuery.isFunction(html);return this.each(function(i){jQuery(this).wrapAll(isFunction?html.call(this,i):html)})},unwrap:function(){return this.parent().each(function(){jQuery.nodeName(this,"body")||jQuery(this).replaceWith(this.childNodes)}).end()}}),jQuery.expr.filters.hidden=function(elem){return elem.offsetWidth<=0&&elem.offsetHeight<=0},jQuery.expr.filters.visible=function(elem){return!jQuery.expr.filters.hidden(elem)};var r20=/%20/g,rbracket=/\[\]$/,rCRLF=/\r?\n/g,rsubmitterTypes=/^(?:submit|button|image|reset|file)$/i,rsubmittable=/^(?:input|select|textarea|keygen)/i;jQuery.param=function(a,traditional){var prefix,s=[],add=function(key,value){value=jQuery.isFunction(value)?value():null==value?"":value,s[s.length]=encodeURIComponent(key)+"="+encodeURIComponent(value)};if(void 0===traditional&&(traditional=jQuery.ajaxSettings&&jQuery.ajaxSettings.traditional),jQuery.isArray(a)||a.jquery&&!jQuery.isPlainObject(a))jQuery.each(a,function(){add(this.name,this.value)});else for(prefix in a)buildParams(prefix,a[prefix],traditional,add);return s.join("&").replace(r20,"+")},jQuery.fn.extend({serialize:function(){return jQuery.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var elements=jQuery.prop(this,"elements");return elements?jQuery.makeArray(elements):this}).filter(function(){var type=this.type;return this.name&&!jQuery(this).is(":disabled")&&rsubmittable.test(this.nodeName)&&!rsubmitterTypes.test(type)&&(this.checked||!rcheckableType.test(type))}).map(function(i,elem){var val=jQuery(this).val();return null==val?null:jQuery.isArray(val)?jQuery.map(val,function(val){return{name:elem.name,value:val.replace(rCRLF,"\r\n")}}):{name:elem.name,value:val.replace(rCRLF,"\r\n")}}).get()}}),jQuery.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(e){}};var xhrId=0,xhrCallbacks={},xhrSuccessStatus={0:200,1223:204},xhrSupported=jQuery.ajaxSettings.xhr();window.ActiveXObject&&jQuery(window).on("unload",function(){for(var key in xhrCallbacks)xhrCallbacks[key]()}),support.cors=!!xhrSupported&&"withCredentials"in xhrSupported,support.ajax=xhrSupported=!!xhrSupported,jQuery.ajaxTransport(function(options){var callback;return support.cors||xhrSupported&&!options.crossDomain?{send:function(headers,complete){var i,xhr=options.xhr(),id=++xhrId;if(xhr.open(options.type,options.url,options.async,options.username,options.password),options.xhrFields)for(i in options.xhrFields)xhr[i]=options.xhrFields[i];options.mimeType&&xhr.overrideMimeType&&xhr.overrideMimeType(options.mimeType),options.crossDomain||headers["X-Requested-With"]||(headers["X-Requested-With"]="XMLHttpRequest");for(i in headers)xhr.setRequestHeader(i,headers[i]);callback=function(type){return function(){callback&&(delete xhrCallbacks[id],callback=xhr.onload=xhr.onerror=null,"abort"===type?xhr.abort():"error"===type?complete(xhr.status,xhr.statusText):complete(xhrSuccessStatus[xhr.status]||xhr.status,xhr.statusText,"string"==typeof xhr.responseText?{text:xhr.responseText}:void 0,xhr.getAllResponseHeaders()))}},xhr.onload=callback(),xhr.onerror=callback("error"),callback=xhrCallbacks[id]=callback("abort"),xhr.send(options.hasContent&&options.data||null)},abort:function(){callback&&callback()}}:void 0}),jQuery.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(text){return jQuery.globalEval(text),text}}}),jQuery.ajaxPrefilter("script",function(s){void 0===s.cache&&(s.cache=!1),s.crossDomain&&(s.type="GET")}),jQuery.ajaxTransport("script",function(s){if(s.crossDomain){var script,callback;return{send:function(_,complete){script=jQuery(" + + diff --git a/dist/index.html b/dist/index.html index 52daae978..d91db16da 100644 --- a/dist/index.html +++ b/dist/index.html @@ -113,6 +113,8 @@ + + diff --git a/dist/scripts/scripts.js b/dist/scripts/scripts.js index bc24feabf..d0dce4dc6 100644 --- a/dist/scripts/scripts.js +++ b/dist/scripts/scripts.js @@ -1,2 +1,2 @@ "use strict";angular.module("underscore",[]).value("_",window._),angular.module("NProgress",[]).value("NProgress",window.NProgress),angular.module("URLify",[]).value("URLify",window.URLify),angular.module("jquery",[]).value("$",window.$),angular.module("moment",[]).value("moment",window.moment),angular.module("bulbsCmsApp",["ngCookies","ngResource","ngSanitize","ngRoute","ui.bootstrap","ui.bootstrap.datetimepicker","restangular","bettyCropper","jquery","underscore","NProgress","URLify","moment"]).config(["$locationProvider","$routeProvider","$sceProvider","routes",function($locationProvider,$routeProvider,$sceProvider,routes){$locationProvider.html5Mode(!0),$routeProvider.when("/cms/app/list/:queue/",{templateUrl:routes.PARTIALS_URL+"contentlist.html",controller:"ContentlistCtrl",reloadOnSearch:!1}).when("/cms/app/edit/:id/",{templateUrl:routes.PARTIALS_URL+"contentedit.html",controller:"ContenteditCtrl"}).when("/cms/app/promotion/",{templateUrl:routes.PARTIALS_URL+"promotion.html",controller:"PromotionCtrl",reloadOnSearch:!1}).when("/cms/app/targeting/",{templateUrl:routes.PARTIALS_URL+"targeting-editor.html",controller:"TargetingCtrl"}).when("/cms/app/pzones/",{templateUrl:routes.PARTIALS_URL+"pzones.html",controller:"PzoneCtrl"}).otherwise({redirectTo:"/cms/app/list/published/"}),$sceProvider.enabled(!1)}]).config(["$provide",function($provide){$provide.decorator("$exceptionHandler",function($delegate){return function(exception,cause){$delegate(exception,cause),window.Raven.captureException(exception)}})}]).run(["$rootScope","$http","$cookies",function($rootScope,$http,$cookies){$http.defaults.headers.post["X-CSRFToken"]=$cookies.csrftoken;var deleteHeaders=$http.defaults.headers.delete||{};deleteHeaders["X-CSRFToken"]=$cookies.csrftoken,$http.defaults.headers.delete=deleteHeaders}]),angular.module("bulbsCmsApp").controller("ContentlistCtrl",["$scope","$http","$timeout","$location","$routeParams","$window","$q","$","_","moment","ContentApi",function($scope,$http,$timeout,$location,$routeParams,$window,$q,$,_,moment,ContentApi){function updateIsMyStuff(){if(!$location.search().authors)return void($scope.myStuff=!1);var authors=$location.search().authors;"string"==typeof authors&&(authors=[authors]),$scope.myStuff=1===authors.length&&authors[0]===$window.current_user?!0:!1}$window.document.title="AVCMS | Content",$scope.pageNumber=$location.search().page||"1",$scope.myStuff=!1,$scope.queue=$routeParams.queue||"all",$scope.search=$location.search().search;var getContentCallback=function(data){$scope.articles=data,$scope.totalItems=data.metadata.count};$scope.getContent=function(){var params={page:$scope.pageNumber};"all"!==$scope.queue&&("published"===$scope.queue?params.before=moment().format("YYYY-MM-DDTHH:mmZ"):"waiting"===$scope.queue?params.status="Waiting for Editor":"draft"===$scope.queue?params.status="Draft":"scheduled"===$scope.queue&&(params.after=moment().format("YYYY-MM-DDTHH:mmZ")));var search=$location.search();for(var prop in search)if(search.hasOwnProperty(prop)){var val=search[prop];val&&"false"!==val&&(params[prop]=val)}ContentApi.all("content").getList(params).then(getContentCallback)},updateIsMyStuff(),$scope.getContent(),$scope.$on("$routeUpdate",function(){updateIsMyStuff()}),$scope.$watch("myStuff",function(){$scope.myStuff?$("#meOnly").bootstrapSwitch("setState",!0,!0):$("#meOnly").bootstrapSwitch("setState",!1,!0)}),$("#meOnly").on("switch-change",function(e,data){var value=data.value;value===!0?($location.search().authors=[$window.current_user],$scope.getContent()):value===!1&&(delete $location.search().authors,$scope.getContent())}),$scope.goToPage=function(page){$location.search(_.extend($location.search(),{page:page})),$scope.getContent()},$scope.sort=function(sort){$location.search().ordering&&0===$location.search().ordering.indexOf(sort)&&(sort="-"+sort),$location.search(_.extend($location.search(),{ordering:sort})),$scope.getContent()},$scope.publishSuccessCbk=function(data){var i;for(i=0;i<$scope.articles.length&&$scope.articles[i].id!==data.article.id;i++);for(var field in data.response)$scope.articles[i][field]=data.response[field];return $q.when()},$scope.trashSuccessCbk=function(){$timeout(function(){$scope.getContent(),$("#confirm-trash-modal").modal("hide")},1500)},$(".expcol").click(function(e){e.preventDefault();var nS="1"===$(this).attr("state")?"0":"1",i=nS?"minus":"plus",t=nS?"Collapse":"Expand",tP=$($(this).attr("href")).find(".panel-collapse");tP.collapse("0"===$(this).attr("state")?"show":"hide"),$(this).html(' '+t+" all"),$(this).attr("state",nS)}),$("#meOnly").bootstrapSwitch()}]).directive("ngConfirmClick",[function(){return{link:function(scope,element,attr){var msg=attr.ngConfirmClick||"Are you sure?",clickAction=attr.confirmedClick;element.bind("click",function(){window.confirm(msg)&&scope.$eval(clickAction)})}}}]),angular.module("bulbsCmsApp").controller("ContenteditCtrl",["$scope","$routeParams","$http","$window","$location","$timeout","$compile","$q","$","IfExistsElse","routes","ContentApi","ReviewApi","Login",function($scope,$routeParams,$http,$window,$location,$timeout,$compile,$q,$,IfExistsElse,routes,ContentApi,ReviewApi,Login){function getContent(){return ContentApi.one("content",$routeParams.id).get().then(getArticleCallback)}function mediaItemExistsCbkFactory(index){return function(media_item){$scope.article.ratings[index].media_item=media_item,$scope.mediaItemCallbackCounter-=1}}function mediaItemDoesNotExistCbkFactory(index){return function(){saveMediaItem(index)}}function saveMediaItem(index){var type=$scope.article.ratings[index].type,mediaItem=$scope.article.ratings[index].media_item;mediaItem=ReviewApi.restangularizeElement(null,mediaItem,type);var q;q=mediaItem.id?mediaItem.put():mediaItem.post(),q.then(function(resp){$scope.article.ratings[index].media_item=resp,$scope.mediaItemCallbackCounter-=1}).catch(saveArticleErrorCbk)}function saveToContentApi(){$("#save-article-btn").html(" Saving"),$scope.article.put().then(saveArticleSuccessCbk,saveArticleErrorCbk)}function saveArticleErrorCbk(data){return 403===data.status?(Login.showLoginModal(),void $("#save-article-btn").html("Save")):($("#save-article-btn").html(" Error!"),400===status&&($scope.errors=data),void $scope.saveArticleDeferred.reject())}function saveArticleSuccessCbk(resp){$("#save-article-btn").html(" Saved!"),setTimeout(function(){$("#save-article-btn").html("Save")},1e3),$scope.article=resp,$scope.errors=null,$location.search("rating_type",null),dirtGone(),$scope.saveArticleDeferred.resolve(resp)}function waitForDirt(){$(".edit-page").one("change input","input,div.editor",function(){window.onbeforeunload=function(){return"You have unsaved changes. Leave anyway?"}})}function dirtGone(){window.onbeforeunload=function(){}}$scope.PARTIALS_URL=routes.PARTIALS_URL,$scope.CONTENT_PARTIALS_URL=routes.CONTENT_PARTIALS_URL,$scope.MEDIA_ITEM_PARTIALS_URL=routes.MEDIA_ITEM_PARTIALS_URL,$scope.CACHEBUSTER=routes.CACHEBUSTER;var getArticleCallback=function(data){$window.article=$scope.article=data,!$location.search().rating_type||data.ratings&&0!==data.ratings.length||($scope.article.ratings=[{type:$location.search().rating_type}]),$scope.$watch("article.detail_image.id",function(newVal,oldVal){$scope.article&&(newVal&&oldVal&&newVal===oldVal||null!==newVal&&(!$scope.article.image||!$scope.article.image.id||newVal&&oldVal&&$scope.article.image&&$scope.article.image.id&&oldVal===$scope.article.image.id||!oldVal&&newVal)&&($scope.article.image={id:newVal,alt:null,caption:null}))})};getContent(),$scope.$watch("article.title",function(){$window.document.title="AVCMS | Editing "+($scope.article&&$(""+$scope.article.title+"").text())}),$("body").removeClass(),$scope.tagDisplayFn=function(o){return o.name},$scope.tagCallback=function(o,input,freeForm){var tagVal=freeForm?o:o.name;IfExistsElse.ifExistsElse(ContentApi.all("tag").getList({ordering:"name",search:tagVal}),{name:tagVal},function(tag){$scope.article.tags.push(tag)},function(value){$scope.article.tags.push({name:value.name,type:"content_tag","new":!0})},function(data,status){403===status&&Login.showLoginModal()}),$(input).val("")},$scope.sectionCallback=function(o,input,freeForm){var tagVal=freeForm?o:o.name;IfExistsElse.ifExistsElse(ContentApi.all("tag").getList({ordering:"name",search:tagVal}),{name:tagVal},function(tag){$scope.article.tags.push(tag)},function(){console.log("Can't create sections.")},function(data,status){403===status&&Login.showLoginModal()}),$(input).val("")},$scope.removeTag=function(e){var tag=$(e.target).parents("[data-tag]").data("tag"),id=tag.id,newtags=[];for(var i in $scope.article.tags)$scope.article.tags[i].id!==id&&newtags.push($scope.article.tags[i]);$scope.article.tags=newtags},$scope.removeAuthor=function(e){var author=$(e.target).parents("[data-author]").data("author"),id=author.id,newauthors=[];for(var i in $scope.article.authors)$scope.article.authors[i].id!==id&&newauthors.push($scope.article.authors[i]);$scope.article.authors=newauthors},$scope.featureTypeDisplayFn=function(o){return o.name},$scope.featureTypeCallback=function(o,input,freeForm){var fVal=freeForm?o:o.name;IfExistsElse.ifExistsElse(ContentApi.all("things").getList({type:"feature_type",q:fVal}),{name:fVal},function(ft){$scope.article.feature_type=ft.name,$("#feature-type-container").removeClass("newtag")},function(value){$scope.article.feature_type=value.name,$("#feature-type-container").addClass("newtag")},function(data,status){403===status&&Login.showLoginModal()})},$scope.authorDisplayFn=function(o){return o.first_name&&o.last_name&&o.first_name+" "+o.last_name||"username: "+o.username},$scope.authorCallback=function(o,input){for(var t in $scope.article.authors)if($scope.article.authors[t].id===o.id)return;$scope.article.authors.push(o),$(input).val("")},$scope.saveArticleDeferred=$q.defer(),$scope.mediaItemCallbackCounter=void 0,$scope.$watch("mediaItemCallbackCounter",function(){0===$scope.mediaItemCallbackCounter&&saveToContentApi()}),$scope.saveArticle=function(){var data=$scope.article;$scope.article.title=$scope.editors.content_title_editor.getContent(),"Published"!==$scope.article.status&&($scope.article.slug=$window.URLify($scope.article.title,50)),$scope.article.subhead=$scope.editors.content_subhead_editor.getContent(),$scope.editors.content_body_editor&&($scope.article.body=$scope.editors.content_body_editor.getContent()),$scope.mediaItemCallbackCounter=data.ratings&&data.ratings.length||saveToContentApi();for(var i in data.ratings){var show;if("tvseason"===data.ratings[i].type){var identifier=data.ratings[i].media_item.identifier;show=data.ratings[i].media_item.show,IfExistsElse.ifExistsElse(ReviewApi.all("tvseason").getList({season:identifier,show:show}),{identifier:identifier,show:show},mediaItemExistsCbkFactory(i),mediaItemDoesNotExistCbkFactory(i),saveArticleErrorCbk)}else if("tvepisode"===data.ratings[i].type){show=data.ratings[i].media_item.show;var season=data.ratings[i].media_item.season,episode=data.ratings[i].media_item.episode;IfExistsElse.ifExistsElse(ReviewApi.all("tvepisode").getList({show:show,season:season,episode:episode}),{show:show,season:season,episode:episode},mediaItemExistsCbkFactory(i),mediaItemDoesNotExistCbkFactory(i),saveArticleErrorCbk)}else saveMediaItem(i)}return $scope.saveArticleDeferred.promise},$scope.displayAuthorAutocomplete=function(obj){return obj.first_name+" "+obj.last_name},waitForDirt(),$("#extra-info-modal").on("shown.bs.modal",function(){$window.picturefill()}),$scope.initEditor=function(name,id,options,articleField){$scope.editors=$scope.editors||{},$scope.editors[name]=new window.Editor(options),angular.element(id+" .editor").bind("input",function(){$scope.article[articleField]=$scope.editors[name].getContent()})},$window.initEditor=$scope.initEditor,$scope.$on("$destroy",function(){for(var editor in $scope.editors)$scope.editors[editor].destroy()}),$scope.addRating=function(type){$scope.article.ratings.push({grade:"",type:type,media_item:{type:type}}),$("#add-review-modal").modal("hide")},$scope.deleteRating=function(index){$scope.article.ratings.splice(index,1)},$scope.publishSuccessCbk=function(){return getContent()},$scope.trashSuccessCbk=function(){$timeout(function(){$window.history.back()},1500)}}]),angular.module("bulbsCmsApp").controller("NavCtrl",["$scope","routes",function($scope,routes){$scope.PARTIALS_URL=routes.PARTIALS_URL,$scope.NAV_LOGO=routes.NAV_LOGO}]),angular.module("bulbsCmsApp").controller("PromotionCtrl",["$scope","$http","$window","$","ContentApi","PromotionApi","promo_options",function($scope,$http,$window,$,ContentApi,PromotionApi,promo_options){$window.document.title=promo_options.namespace+" | Promotion Tool",$scope.$watch("pzone",function(pzone){$scope.promotedArticles=pzone&&pzone.content&&pzone.content.length?pzone.content.slice(0):[{hey_checkthis:!0,title:"Nothing Promoted!",feature_type:"Click an article on the right and use 'Insert'"}]}),$scope.getPzones=function(){ContentApi.all("contentlist").getList().then(function(data){$scope.pzones=data,$scope.pzone=data[0]}).catch(function(){alert("Content list does not exist.")})};var getContentCallback=function(data){$scope.articles=data,$scope.totalItems=data.metadata.count};$scope.getContent=function(){ContentApi.all("content").getList({published:!0}).then(getContentCallback)},$scope.$on("$viewContentLoaded",function(){$scope.getPzones(),$scope.getContent()}),$scope.articleIsInPromotedArticles=function(id){if($scope.promotedArticles)for(var i in $scope.promotedArticles)if($scope.promotedArticles[i].id===id)return!0;return!1};var pA=$(".promotion-area"),pC=$(".promotion-container");$scope.insertArticleMode=function(article){$scope.selectedArticle=article,pA.addClass("select-mode"),pC.off("click"),pC.on("click",".promotion-area.select-mode .article-container",function(){var index=$(this).parents("[data-index]").data("index")-0;$scope.insertArticle(index),pA.removeClass("select-mode"),$scope.$apply()})},$scope.insertArticle=function(index){var limit=promo_options.upper_limits[$scope.pzone.name];$scope.promotedArticles[index]&&$scope.promotedArticles[index].id?$scope.promotedArticles.splice(index,0,$scope.selectedArticle):$scope.promotedArticles.splice(index,1,$scope.selectedArticle),limit&&$scope.promotedArticles.length>limit&&$scope.promotedArticles.pop($scope.promotedArticles.length)},$scope.replaceArticleMode=function(article){$scope.selectedArticle=article,pA.addClass("select-mode"),pC.off("click"),pC.on("click",".promotion-area.select-mode .article-container",function(){var index=$(this).parents("[data-index]").data("index");$scope.replaceArticle(index),pA.removeClass("select-mode"),$scope.$apply()})},$scope.replaceArticle=function(index){$scope.promotedArticles.splice(index,1,$scope.selectedArticle)},$scope.save=function(){var items=$scope.promotedArticles.slice(0);items[0].id||items.shift(),$(".save-button").html(' Saving');var payload=$scope.pzone;payload.content=$scope.promotedArticles[0].hey_checkthis?[]:$scope.promotedArticles;var pzone=ContentApi.restangularizeElement(null,payload,"contentlist");pzone.put().then(function(data){$scope.pzone.content=data.content,$(".save-button").removeClass("btn-danger").addClass("btn-success").html(' Saved'),window.setTimeout(function(){$(".save-button").html("Save")},2e3)}).catch(function(){$(".save-button").removeClass("btn-success").addClass("btn-danger").html(' Error'),window.setTimeout(function(){$(".save-button").html("Save")},2e3)})},$scope.moveUp=function(index){if(0!==index){var toMove=$scope.promotedArticles[index];$scope.promotedArticles[index]=$scope.promotedArticles[index-1],$scope.promotedArticles[index-1]=toMove}},$scope.moveDown=function(index){if(index!==$scope.promotedArticles.length-1){var toMove=$scope.promotedArticles[index];$scope.promotedArticles[index]=$scope.promotedArticles[index+1],$scope.promotedArticles[index+1]=toMove}},$scope.remove=function(index){$scope.promotedArticles.splice(index,1)},$("body").on("shown.bs.collapse","#page-prev .collapse",function(){$window.picturefill()})}]),angular.module("bulbsCmsApp").controller("PzoneCtrl",["$scope","$http","$window","$","ContentApi","PromotionApi","routes",function($scope,$http,$window,$,ContentApi,PromotionApi,routes){function getPzone(){PromotionApi.one("pzone/"+$scope.pzoneName).get().then(function(data){$scope.pzone=data}).catch(function(){console.log("Zone does not exist.")})}$window.document.title="AVCMS | Pzone Editor",$scope.pzoneName="homepage-one",$scope.newContentId=null,$scope.$watch("pzoneName",function(){getPzone()}),$scope.typeChanged=function(){console.log("Type changed!"),void 0!==$scope.pzone&&($scope.pzone.data={})};var getContentCallback=function(data){$scope.articles=data,$scope.totalItems=data.metadata.count};$scope.getContent=function(){ContentApi.getList("content").then(getContentCallback)},$scope.getContent(),$scope.getPZoneTemplate=function(){return routes.PARTIALS_URL+"pzones/"+$scope.pzone.zone_type+".html"},$scope.remove=function(contentId){var index=$scope.pzone.data.content_ids.indexOf(contentId);-1!==index&&$scope.pzone.data.content_ids.splice(index,1)},$scope.add=function(prepend){void 0===$scope.pzone.data.content_ids&&($scope.pzone.data.content_ids=[]),prepend&&$scope.newContentIdPrepend?$scope.pzone.data.content_ids.unshift($scope.newContentIdPrepend):$scope.newContentId&&$scope.pzone.data.content_ids.push($scope.newContentId),$scope.newContentId=null,$scope.newContentIdPrepend=null},$scope.save=function(){$("#save-pzone-btn").html(' Saving');var pzone=ContentApi.restangularizeElement(null,$scope.pzone,"pzone/"+$scope.pzoneName);pzone.put().then(function(){$("#save-pzone-btn").html(' Saved!'),window.setTimeout(function(){$("#save-pzone-btn").html("Save")},2e3)}).catch(function(){$("#save-pzone-btn").html(' Saved!'),window.setTimeout(function(){$("#save-pzone-btn").html("Save")},2e3)})}}]),angular.module("bulbsCmsApp").controller("TargetingCtrl",["$scope","$http","$window","$q","$location","tar_options","NProgress",function($scope,$http,$window,$q,$location,tar_options,NProgress){$window.document.title=tar_options.namespace+" | Targeting Editor",NProgress.configure({minimum:.4});var canceller;$scope.search=function(url){url&&("undefined"==typeof canceller?canceller=$q.defer():(canceller.resolve(),NProgress.set(0),canceller=$q.defer()),NProgress.start(),$http({method:"GET",url:tar_options.endpoint,timeout:canceller.promise,params:{url:$scope.url}}).success(function(data){$scope.targetingArray=[];for(var k in data)$scope.targetingArray.push([k,data[k]]);NProgress.done()}).error(function(data,status){404==status&&($scope.targetingArray=[],$scope.targetingArray.push(["",""]),NProgress.done())}))},$scope.save=function(){var data={};for(var i in $scope.targetingArray)data[$scope.targetingArray[i][0]]=$scope.targetingArray[i][1];NProgress.start(),$http({method:"POST",url:tar_options.endpoint+"?url="+$scope.url,data:data}).success(function(){NProgress.done()}).error(function(){NProgress.done()})},$scope.keyHandler=function(event,url){13===event.keyCode?this.search(url):27===event.keyCode&&(event.currentTarget.value="")};var search=$location.search();search&&search.url&&($scope.url=decodeURIComponent(search.url))}]),angular.module("bulbsCmsApp").controller("ContentworkflowCtrl",["$scope","$http","$modal","$window","moment","routes","TIMEZONE_LABEL",function($scope,$http,$modal,$window,moment,routes,TIMEZONE_LABEL){$scope.TIMEZONE_LABEL=TIMEZONE_LABEL,$scope.trashContentModal=function(articleId){return $modal.open({templateUrl:routes.PARTIALS_URL+"modals/confirm-trash-modal.html",controller:"TrashcontentmodalCtrl",scope:$scope,resolve:{articleId:function(){return articleId}}})},$scope.pubTimeModal=function(article){return $modal.open({templateUrl:routes.PARTIALS_URL+"modals/choose-date-modal.html",controller:"PubtimemodalCtrl",scope:$scope,resolve:{article:function(){return article}}})},$scope.sendToEditorModal=function(article){return $modal.open({templateUrl:routes.PARTIALS_URL+"modals/send-to-editor-modal.html",controller:"SendtoeditormodalCtrl",scope:$scope,resolve:{article:function(){return article}}})},$scope.getStatus=function(article){return article&&article.published?moment(article.published)>moment()?"scheduled":"published":"unpublished"}}]),angular.module("bulbsCmsApp").controller("TrashcontentmodalCtrl",["$scope","$http","$modalInstance","$","Login","articleId",function($scope,$http,$modalInstance,$,Login,articleId){console.log("trash content modal ctrl here"),console.log(articleId),$modalInstance.result.then(function(){$("#trash-confirm-button").html("Delete")},function(){$("#trash-confirm-button").html("Delete")}),$scope.trashContent=function(){return console.log("trash content here"),$("#trash-confirm-button").html(' Trashing'),$http({method:"POST",url:"/cms/api/v1/content/"+articleId+"/trash/"}).success(function(){console.log("trash success"),$scope.trashSuccessCbk(),$modalInstance.close()}).error(function(data,status){404===status?($scope.trashSuccessCbk(),$modalInstance.close()):403===status?(Login.showLoginModal(),$modalInstance.dismiss()):$("#trash-confirm-button").html(' Error!')})}}]),angular.module("bulbsCmsApp").controller("PubtimemodalCtrl",["$scope","$http","$modal","$modalInstance","$","moment","Login","routes","article","TIMEZONE_OFFSET",function($scope,$http,$modal,$modalInstance,$,moment,Login,routes,article,TIMEZONE_OFFSET){$scope.article=article,$scope.$watch("pickerValue",function(newVal){var pubTimeMoment=moment(newVal).zone(TIMEZONE_OFFSET);$scope.datePickerValue=moment().year(pubTimeMoment.year()).month(pubTimeMoment.month()).date(pubTimeMoment.date()),$scope.timePickerValue=moment().hour(pubTimeMoment.hour()).minute(pubTimeMoment.minute())}),$modalInstance.result.then(function(){$("#save-pub-time-button").html("Publish")},function(){$("#save-pub-time-button").html("Publish")});var modelDateFormat="YYYY-MM-DDTHH:mmZ";$scope.setTimeShortcut=function(shortcut){if("now"==shortcut){var now=moment().zone(TIMEZONE_OFFSET);$scope.pickerValue=now}if("midnight"==shortcut){var midnight=moment().zone(TIMEZONE_OFFSET).hour(24).minute(0);$scope.pickerValue=midnight}},$scope.setDateShortcut=function(shortcut){var today=moment().zone(TIMEZONE_OFFSET);"today"==shortcut&&($scope.datePickerValue=moment().year(today.year()).month(today.month()).date(today.date())),"tomorrow"==shortcut&&($scope.datePickerValue=moment().year(today.year()).month(today.month()).date(today.date()+1))},$scope.setPubTime=function(){if(!$scope.article.feature_type)return $modalInstance.dismiss(),void $modal.open({templateUrl:routes.PARTIALS_URL+"modals/pubtime-validation-modal.html"});var newDate=moment($scope.datePickerValue),newTime=moment($scope.timePickerValue),newDateTime=moment().zone(TIMEZONE_OFFSET).year(newDate.year()).month(newDate.month()).date(newDate.date()).hour(newTime.hour()).minute(newTime.minute()).format(modelDateFormat),data={published:newDateTime};$("#save-pub-time-button").html(' Saving'),$http({url:"/cms/api/v1/content/"+$scope.article.id+"/publish/",method:"POST",data:data}).success(function(resp){$scope.article.published=resp.published,$scope.publishSuccessCbk&&$scope.publishSuccessCbk({article:$scope.article,response:resp}),$modalInstance.close()}).error(function(error,status){403===status&&Login.showLoginModal(),$modalInstance.dismiss()})},$scope.article.published?$scope.pickerValue=moment($scope.article.published):$scope.setTimeShortcut("now")}]),angular.module("bulbsCmsApp").controller("LoginmodalCtrl",["$scope","Login","$modalInstance","$",function($scope,Login,$modalInstance,$){$scope.login=function(){var username=$("input[name='username']").val(),password=$("input[name='password']").val();Login.login(username,password).then(function(){$modalInstance.close()},function(){$modalInstance.dismiss()})}}]),angular.module("bulbsCmsApp").controller("UnpublishCtrl",["$scope","$http","$q",function($scope,$http,$q){$scope.unpublish=function(article){var data={published:!1},deferred=$q.defer();return $http({url:"/cms/api/v1/content/"+article.id+"/publish/",method:"POST",data:data}).success(function(data){deferred.resolve({article:article,response:data})}).error(function(data){deferred.reject(data)}),deferred.promise}}]),angular.module("bulbsCmsApp").directive("activeNav",["$location",function($location){return{template:'
    • {{label}}
    • ',restrict:"E",scope:{},replace:!0,link:function(scope,element,attrs){scope.href=attrs.href,scope.label=attrs.label,0===$location.path().indexOf(scope.href)&&element.addClass("active")}}}]),angular.module("bulbsCmsApp").directive("articlecontainer",["routes","LOADING_IMG_SRC",function(routes,LOADING_IMG_SRC){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"promotion-tool-article-container.html",scope:{article:"="},link:function(scope,element,attrs){scope.LOADING_IMG_SRC=LOADING_IMG_SRC,scope.ratio=attrs.ratio}}}]),angular.module("bulbsCmsApp").directive("bulbsAutocomplete",["$http","$location","$compile","$timeout","$","Login",function($http,$location,$compile,$timeout,$,Login){return{restrict:"A",scope:!0,link:function(scope,element,attrs){function getAutocompletes(val){$timeout.cancel(inputTimeout),inputCounter=0,$http({method:"GET",url:attrs.resourceUrl+val}).success(function(data){var results=data.results||data;scope.autocomplete_list=results.splice(0,5)}).error(function(data,status){403===status&&Login.showLoginModal()})}scope.displayfn=scope[attrs.displayfn],scope.callback=scope[attrs.callback];var $elem=$(element).find("input");$elem.attr("autocomplete","off");var dropdown=$($compile($("#autocomplete-dropdown-template").html())(scope));$(dropdown).css({position:"absolute",top:$elem.position().top+$elem.outerHeight(),left:$elem.position().left,minWidth:$elem.outerWidth(),display:"none"}),$elem.parent().append(dropdown),$(dropdown).fadeIn("fast"),scope.$watch(function(){return{top:$elem.position().top+$elem.outerHeight(),left:$elem.position().left,minWidth:$elem.outerWidth()}},function(newValue){$(dropdown).css({top:newValue.top,left:newValue.left,minWidth:newValue.minWidth})},!0);var inputTimeout,inputCounter=0;$elem.on("focus",function(){$elem.on("input",function(){var val=$elem.val();""===val?scope.autocomplete_list=[]:($timeout.cancel(inputTimeout),inputTimeout=$timeout(function(){getAutocompletes(val)},200),inputCounter>2&&getAutocompletes(val))}),$(dropdown).fadeIn("fast")}),scope.blurTimeout,$elem.on("blur",function(){$(dropdown).fadeOut("fast")}),$(dropdown).on("mouseover",".entry",function(){$(dropdown).find(".selected").removeClass("selected"),$(this).addClass("selected")}),$elem.on("keyup",function(e){if(40===e.keyCode)if(0===$("div.selected",dropdown).length)$("div.entry",dropdown).first().addClass("selected");else{var curDownSelect=$("div.selected",dropdown),curDownSelectNext=curDownSelect.next("div");0===curDownSelectNext.length?$("div.entry",dropdown).first().addClass("selected"):curDownSelectNext.addClass("selected"),curDownSelect.removeClass("selected")}if(38===e.keyCode)if(0===$("div.selected",dropdown).length)$("div.entry",dropdown).last().addClass("selected");else{var curSelect=$("div.selected",dropdown),curSelectNext=curSelect.prev("div");0===curSelectNext.length?$("div.entry",dropdown).last().addClass("selected"):curSelectNext.addClass("selected"),curSelect.removeClass("selected")}if(13===e.keyCode){var selected=$("div.selected",dropdown);0===selected.length&&scope.onClick($elem.val(),!0),selected.click()}}),scope.onClick=function(o,freeForm){scope.callback(o,$elem,freeForm||!1),scope.autocomplete_list=[]}}}}]),angular.module("bulbsCmsApp").directive("bettyeditable",["$http","routes","BC_API_KEY",function($http,routes){return{replace:!0,restrict:"E",templateUrl:routes.PARTIALS_URL+"bettyeditable.html",scope:{imageId:"=",ratio:"@"},controller:["$scope","$element","$attrs","$http","routes","BC_API_KEY",function($scope,$element,$attrs,$http,routes,BC_API_KEY){$scope.imageData=null,$scope.getImageData=function(){$http({method:"GET",url:routes.IMAGE_SERVER_URL+"/api/"+$scope.imageId,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},transformRequest:angular.identity}).success(function(response){$scope.imageData=response,$scope.showImage()}).error(function(data,status){404===status&&($scope.imageData={width:1200,selections:{"16x9":{x0:0,y0:0,x1:1200,y1:675}}},$scope.showImage())})},$scope.showImage=function(){if(null===$scope.imageData)return console.log("Getting selections!"),void $scope.getImageData();var pictureDiv=$element.find("div")[1],pushdownDiv=$element.find("div")[0];pictureDiv.className="picture";var ratioWidth=parseInt($scope.ratio.split("x")[0],10),ratioHeight=parseInt($scope.ratio.split("x")[1],10);pushdownDiv.style.paddingTop=ratioHeight/ratioWidth*100+"%",pictureDiv.style.backgroundImage="url("+routes.IMAGE_SERVER_URL+"/"+$scope.imageId+"/original/1200.jpg)";var selection=$scope.imageData.selections[$scope.ratio],leftPosition=selection.x0/1200*100,topPosition=selection.y0/(1200*ratioHeight/ratioWidth)*100;pictureDiv.style.backgroundPosition=leftPosition+"% "+topPosition+"%, center",pictureDiv.style.backgroundSize="cover"},$scope.uploadSuccess=function(response){$scope.imageId=response.id,$scope.imageData=response,$scope.showImage()},$scope.upload=function(){if(1!=this.files.length)return void console.log("We need exactly one image!");var file=this.files[0];if(0!=file.type.indexOf("image/"))return void console.log("Not an image!");file.size>68e5&&console.log("The file is too large!");var imageData=new FormData;imageData.append("image",file),$http({method:"POST",url:routes.IMAGE_SERVER_URL+"/api/new",headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:imageData,transformRequest:angular.identity}).success($scope.uploadSuccess)}}],link:function(scope,element){var input=element.find("input");input.on("change",scope.upload);var pictureDiv=element.find("div")[1],pushdownDiv=element.find("div")[0],ratioWidth=parseInt(scope.ratio.split("x")[0],10),ratioHeight=parseInt(scope.ratio.split("x")[1],10);pushdownDiv.style.paddingTop=ratioHeight/ratioWidth*100+"%",scope.imageId?scope.showImage():(pictureDiv.className="picture fa fa-picture-o",element.on("click",function(e){e.stopPropagation(),input[0].click()}))}}}]),angular.module("bulbsCmsApp").directive("bettyimage",["$http","routes",function($http,routes){return{replace:!0,restrict:"E",templateUrl:routes.PARTIALS_URL+"bettyimage.html",scope:{image:"=",ratio:"=",width:"@"},controller:["$scope",function(){}],link:function(scope,element){scope.width=parseInt(scope.width,10);{var ratioWidth=parseInt(scope.ratio.split("x")[0],10),ratioHeight=parseInt(scope.ratio.split("x")[1],10);scope.width*ratioHeight/ratioWidth+"px"}element.css("width",scope.width+"px"),element.css("height",scope.width*ratioHeight/ratioWidth+"px");var selection=scope.image.selections[scope.ratio],selectionWidth=selection.x1-selection.x0,scale=scope.width/selectionWidth,requestWidth=Math.round(scale*(scope.image.width-selectionWidth)+scope.width);element.css("background-image","url("+routes.IMAGE_SERVER_URL+"/"+scope.image.id+"/original/"+requestWidth+".jpg)"),element.css("background-position",scale*selection.x0*-1+"px "+scale*selection.y0*-1+"px")}}}]),angular.module("bulbsCmsApp").directive("createContent",["$http","$window","$","IfExistsElse","Login","ContentApi","routes",function($http,$window,$,IfExistsElse,Login,ContentApi,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"create-content.html",controller:["$scope",function($scope){function saveArticle(){$("button.go").html(' Going'),$http({url:"/cms/api/v1/content/?doctype="+$scope.contentType,method:"POST",data:$scope.init}).success(function(resp){var new_id=resp.id,new_path="/cms/app/edit/"+new_id+"/"; -$scope.rating_type&&(new_path+="?rating_type="+$scope.rating_type),$window.location.href=$window.location.origin+new_path}).error(function(){console.log("wow. error."),$("button.go").html(' Error!'),$scope.gotSave=!1})}$scope.gotTags=!1,$scope.gotUser=!1,$scope.gotSave=!1,$scope.$watch(function(){return $scope.gotTags&&$scope.gotUser&&$scope.gotSave},function(val){val&&saveArticle($scope.init)}),$scope.newArticle=function(){var init={title:$scope.newTitle};angular.extend($scope.init,init),$scope.tag?IfExistsElse.ifExistsElse(ContentApi.all("tag").getList({ordering:"name",search:$scope.tag}),{slug:$scope.tag},function(tag){$scope.init.tags=[tag],$scope.gotTags=!0},function(value){console.log("couldnt find tag "+value.slug+" for initial value")},function(data,status){403===status&&Login.showLoginModal()}):$scope.gotTags=!0,IfExistsElse.ifExistsElse(ContentApi.all("user").getList({ordering:"name",search:$window.current_user}),{username:$window.current_user},function(user){$scope.init.authors=[user],$scope.gotUser=!0},function(){console.log("are you bruce willis in sixth sense? dunno.")},function(data,status){403===status&&Login.showLoginModal()}),$scope.gotSave=!0}}],link:function(scope,element){$(element).find("a.create-content").on("click",function(){$("a.create-content.active").removeClass("active"),$(this).addClass("active")}),$(element).find("a.create-content").on("click",function(){return scope.contentTypeLabel=$(this).text(),scope.contentType=$(this).data("content_type")||null,scope.init=$(this).data("init")||{},scope.tag=$(this).data("tag")||null,scope.rating_type=$(this).data("rating_type")||null,scope.$apply(),$(this).hasClass("go-next")&&$("#create button.next-pane").click(),!0}),$("button.next-pane:not(.hide)").on("click",function(){console.log("next clicked"),console.log(scope.contentType),console.log(scope.init),$("#createcontent-01").addClass("hidden"),$("#createcontent-02").removeClass("hidden"),$("button.next-pane:not(.hide)").addClass("hidden"),$(".new-title").focus()}),$(element).find(".new-title").on("keydown",function(e){13===e.keyCode&&$(element).find(".go").click()})}}}]),angular.module("bulbsCmsApp").directive("devicepreview",["$","routes",function($,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"devicepreview.html",link:function(){var pP=$("#page-prev"),tN=pP.find(".nav a"),cO=pP.find(".tab-content .active");tN.click(function(e){var newId=$(this).attr("href").split("#")[1];e.preventDefault(),cO.attr("id",newId)}),$("#page-prev").on("show.bs.collapse",function(){$(this).find(".fa").removeClass("fa-plus-square-o").addClass("fa-minus-square-o")}),$("#page-prev").on("hide.bs.collapse",function(){$(this).find(".fa").removeClass("fa-minus-square-o").addClass("fa-plus-square-o")})}}}]),angular.module("bulbsCmsApp").directive("filterwidget",["$http","$location","$window","$timeout","$","routes",function($http,$location,$window,$timeout,$,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"filterwidget.html",link:function(scope,element){function getAutocompletes(search){return $timeout.cancel(filterInputTimeout),filterInputCounter=0,search.length<1?(scope.autocompleteArray=[],void scope.$apply()):void $http({url:"/cms/api/v1/things/?type=tag&type=feature_type&type=author",method:"GET",params:{q:search}}).success(function(data){scope.autocompleteArray=data})}function arrowSelect(direction){var $toSelect,$entries=$element.find(".entry"),$selected=$element.find(".entry.selected");$selected.length>0?("up"===direction&&($toSelect=$selected.first().prev()),"down"===direction&&($toSelect=$selected.first().next())):("up"===direction&&($toSelect=$entries.last()),"down"===direction&&($toSelect=$entries.first())),scope.selectEntry($toSelect)}function applyFilterChange(filterObject){filterObject.page=1,$location.search(filterObject),scope.getContent(),scope.autocompleteArray=[],$input.trigger("blur")}function getQueryToLabelMappings(type,query){scope.queryToLabelMappings=scope.queryToLabelMappings||{},query in scope.queryToLabelMappings||$http({url:"/cms/api/v1/things/?type="+type,method:"GET",params:{q:query}}).success(function(data){for(var i in data)scope.queryToLabelMappings[data[i].value]=data[i].name})}var $element=$(element),$input=$element.find("input");scope.searchTerm,scope.autocompleteArray=[];var filterInputTimeout,filterInputCounter=0;$input.on("input",function(){var search=$input.val();scope.searchTerm=search,$timeout.cancel(filterInputTimeout),filterInputTimeout=$timeout(function(){getAutocompletes(search)},200),filterInputCounter>2&&getAutocompletes(search)}),$input.on("keyup",function(e){38===e.keyCode&&arrowSelect("up"),40===e.keyCode&&arrowSelect("down"),13===e.keyCode&&($element.find(".selected").length>0?$element.find(".selected").click():scope.addFilter("search",$input.val()))}),$element.find(".search-button").on("click",function(){scope.addFilter("search",$input.val())}),$element.find(".clear-button").on("click",function(){$(this).prev("input").val(""),scope.filterObjects={},applyFilterChange({})}),$element.on("mouseover",".entry",function(){scope.selectEntry(this)}),scope.selectEntry=function(entry){$element.find(".selected").removeClass("selected"),$(entry).addClass("selected")},$input.on("blur",function(){$element.find(".dropdown-menu").fadeOut(200)}),$input.on("focus",function(){$element.find(".dropdown-menu").fadeIn(200)}),scope.addFilter=function(type,newFilterValue){var filterObject=$location.search();"search"===type?filterObject.search=newFilterValue:(filterObject[type]||(filterObject[type]=[]),"string"==typeof filterObject[type]&&(filterObject[type]=[filterObject[type]]),filterObject[type].push(newFilterValue),$input.val("")),applyFilterChange(filterObject),scope.filterInputValue=""},scope.deleteFilter=function(key){var filterObject=$location.search(),toDelete=scope.filterObjects[key];"string"==typeof filterObject[toDelete.type]&&(filterObject[type]=[filterObject[type]]);var toSplice;for(var i in filterObject[toDelete.type])if(filterObject[toDelete.type][i]===toDelete.query){toSplice=i;break}filterObject[toDelete.type].splice(i,1),filterObject.search=$input.val(),delete scope.filterObjects[key],applyFilterChange(filterObject)},scope.$watch("locationSearch",function(search){if(scope.filterObjects={},"undefined"!=typeof search){var filterParamsToTypes={authors:"author",tags:"tag",feature_types:"feature_type"};for(var filterParam in filterParamsToTypes){var filterType=filterParamsToTypes[filterParam];"string"==typeof search[filterParam]&&(search[filterParam]=[search[filterParam]]);for(var i in search[filterParam]){var value=search[filterParam][i];scope.filterObjects[filterType+value]={query:value,type:filterParam},getQueryToLabelMappings(filterType,value)}}search.search&&(scope.filterInputValue=search.search)}}),scope.$on("$routeUpdate",function(){scope.locationSearch=$location.search()}),scope.locationSearch=$location.search()}}}]),angular.module("bulbsCmsApp").directive("imagedrawer",["$http","$window","$","routes","BC_API_KEY",function($http,$window,$,routes,BC_API_KEY){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"imagedrawer.html",scope:{openImageDrawer:"=",closeImageDrawer:"=",article:"="},controller:["$scope",function($scope){function scaleSelection(scale,selection){return[Math.floor(scale*selection[0]),Math.floor(scale*selection[1]),Math.floor(scale*selection[2]),Math.floor(scale*selection[3])]}$scope.current_image={},$scope.$watch("current_image",function(){$scope.library_images=prependCurrentImage($scope.library_images,$scope.current_image)}),$scope.library_images=[];var prependCurrentImage=function(library,current_image){var new_library=library;if(current_image.id){for(var i in new_library)if(new_library[i].id===current_image.id){new_library.splice(i,1);break}new_library.unshift(current_image)}return new_library},refreshImageLibrary=function(params){params=params||{},$http({method:"GET",url:routes.BC_ADMIN_URL+"/api/search",params:params,headers:{"X-Betty-Api-Key":BC_API_KEY}}).success(function(data){$scope.library_images=prependCurrentImage(data.results,$scope.current_image)})};$scope.drawerUpload=function(){$window.uploadImage({onProgress:function(){},onSuccess:function(data){refreshImageLibrary(),$scope.onChangeFn(data),$scope.current_image=data},onError:$scope.onCancelFn,onCancel:$scope.onCancelFn})};var refreshCurrentImage=function(id,field){$http({url:routes.BC_ADMIN_URL+"/api/"+id,method:"GET",headers:{"X-Betty-Api-Key":BC_API_KEY}}).success(function(data){field?$scope.current_image[field]=data[field]:$scope.current_image=data,$window.picturefill(!0)}).error(function(){$scope.current_image={}})};$window.refreshCurrentImage=refreshCurrentImage,$scope.$watch("imageLibrarySearch",function(){refreshImageLibrary({q:$scope.imageLibrarySearch})}),$scope.openImageDrawer=function(){var oldId,onChangeFn,onSaveFn,onCancelFn;"function"==typeof arguments[0]?(oldId=null,onChangeFn=arguments[0],onSaveFn=arguments[1],onCancelFn=arguments[2]):(oldId=arguments[0],onChangeFn=arguments[1],onSaveFn=arguments[2],onCancelFn=arguments[3]),$("#image-drawer").off("click"),$("#image-drawer").on("click","#image-library.image",function(){var id=$(this).data("imageId");refreshCurrentImage(id),onChangeFn(id)}),oldId&&($scope.original_image=oldId),refreshCurrentImage(oldId),$scope.oldId=oldId,$scope.onChangeFn=onChangeFn,$scope.onSaveFn=onSaveFn,$scope.onCancelFn=function(id){$scope.original_image&&refreshCurrentImage($scope.original_image),onCancelFn(id)},$("body").addClass("image-drawer-cropper-open"),refreshImageLibrary()},$window.openImageDrawer=$scope.openImageDrawer,$scope.openImageLibrary=function(){$scope.libraryOpen=!0,$("body").addClass("image-drawer-library-open"),$window.picturefill(!0)},$scope.closeImageDrawer=function(){$("body").removeClass("image-drawer-cropper-open"),$("body").removeClass("image-drawer-library-open"),$window.picturefill()},$scope.closeImageLibrary=function(action){"save"===action&&$scope.onSaveFn(),"cancel"===action&&$scope.onCancelFn($scope.oldId),$("body").removeClass("image-drawer-library-open"),$scope.libraryOpen=!1},$scope.saveImageData=function(e){$window.saveImageData(e)},$scope.saveNewCrop=function(image,ratio){image.selections[ratio]={x0:user_selection_scaled[0],y0:user_selection_scaled[1],x1:user_selection_scaled[2],y1:user_selection_scaled[3]},$scope.$apply(),$window.saveNewCrop(image,ratio,user_selection_scaled,{onSuccess:function(){refreshCurrentImage(image.id,"selections")}})};var jcrop_api,user_selection,user_selection_scaled;$("#cropperModal").on("hidden.bs.modal",function(){jcrop_api.destroy()}),$("#cropperModal").on("shown.bs.modal",function(){$window.picturefill()}),$scope.cropImage=function(image,ratio){var width=500;$("#cropper-img").attr("src",routes.IMAGE_SERVER_URL+"/"+image.id+"/original/"+width+".jpg");var aspectWidth=ratio.split("x")[0],aspectHeight=ratio.split("x")[1],scale=width/image.width,selection=[image.selections[ratio].x0,image.selections[ratio].y0,image.selections[ratio].x1,image.selections[ratio].y1],onSelect=function(c){var selection=[c.x,c.y,c.x2,c.y2];user_selection=selection,user_selection_scaled=scaleSelection(1/scale,selection)};$("#cropper-modal-save-button").unbind("click"),$("#cropper-modal-save-button").click(function(){$scope.saveNewCrop(image,ratio)}),$("#cropperModal").modal("show"),$("#cropper-img").Jcrop({onSelect:onSelect,allowMove:!0,allowResize:!0,aspectRatio:aspectWidth/aspectHeight},function(){jcrop_api=this,jcrop_api.setOptions({aspectRatio:aspectWidth/aspectHeight}),this.focus();scaleSelection(scale,selection);this.setSelect(scaleSelection(scale,selection))})}}],link:function(scope){function preventDefault(e){e=e||window.event,e.preventDefault&&e.preventDefault(),e.returnValue=!1}scope.IMAGE_SERVER_URL=routes.IMAGE_SERVER_URL,document.getElementById("image-cropper").onmousewheel=function(e){document.getElementById("image-cropper").scrollTop-=e.wheelDeltaY,preventDefault(e)},document.getElementById("image-library-body").onmousewheel=function(e){document.getElementById("image-library-body").scrollTop-=e.wheelDeltaY,preventDefault(e)}}}}]),angular.module("bulbsCmsApp").directive("listinput",["$","routes",function($,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"listinput.html",scope:{model:"="},link:function(scope,element,attrs){scope.label=attrs.label,scope.noun=attrs.noun,element.find("input")[0].setAttribute("name",attrs.noun),element.find("input").bind("focus",function(){$(element).find(".preview").hide(),$(element).find(".all-container").show()}),element.find("input").bind("blur",function(){$(element).find(".all-container").hide(),$(element).find(".preview").show()}),element.find("input").bind("keyup",function(e){if(13===e.keyCode){var value=$(this).val();value.length>0&&(scope.model||(scope.model=[]),scope.model.push($(this).val()),scope.$apply(),$(this).val(""))}})}}}]),angular.module("bulbsCmsApp").directive("videoUpload",["$http","$window","$timeout","$sce","$","routes",function($http,$window,$timeout,$sce,$,routes){return{templateUrl:routes.PARTIALS_URL+"mainvideo.html",scope:{article:"="},restrict:"E",link:function(scope,element){function abortUpload(){setProgress(0),scope.req&&scope.req.abort(),scope.video={},setProgress(0)}function abortEncode(){$.ajax("https://app.zencoder.com/api/v2/jobs/"+scope.video.job_id+"/cancel.json?api_key="+$window.videoAttrs.zencoderApiKey,{type:"PUT",success:function(){scope.video.status=3,fakeInput.val("Encoding failed! Please try again.")}})}function setProgress(progress){return 0===progress||100===progress?void progressEl.hide():void((0===scope.lastProgress||Math.abs(progress-scope.lastProgress)>2)&&(progressBar.css("width",Math.floor(progress)+"%"),scope.lastProgress=progress,progressEl.show()))}function updateEncodeProgress(){progressBar.addClass("progress-bar-success"),delete $http.defaults.headers.common["X-Requested-With"],$http({url:"https://app.zencoder.com/api/v2/jobs/"+scope.video.job_id+"/progress.json",method:"GET",params:{api_key:$window.videoAttrs.zencoderApiKey},useXDomain:!0}).success(function(data){"waiting"===data.state||"pending"===data.state||"processing"===data.state?(scope.video.status=2,data.progress>5?(setProgress(data.progress),$timeout(updateEncodeProgress,500)):$timeout(updateEncodeProgress,2e3)):(setProgress(0),"finished"===data.state&&(scope.video.status=1),("failed"===data.state||"cancelled"===data.state)&&(scope.video.status=3,fakeInput.val("Encoding failed! Please try again.")))}).error(function(){$(".alert-danger").fadeIn().delay(1e3).fadeOut()})}console.log("video upload here"),console.log(scope.video_id),scope.$watch("article.video",function(){scope.article.video&&(scope.embedUrl=$sce.trustAsUrl("/videos/embed?id="+scope.article.video),$http({method:"GET",url:"/videos/api/video/"+scope.article.video+"/"}).success(function(data){console.log("getting video from API"),console.log(data),scope.video=data,$window.initVideoWidget(data.id)}))}),scope.$watch("video",function(){});var progressEl=(element.find("label.btn"),element.find("div.progress")),progressBar=element.find("div.progress-bar"),fakeInput=(element.find("div.progress span"),element.find("input.fake-input"));scope.lastProgress=0,scope.addVideo=function(){console.log("chooseFile"),$window.uploadVideo(element.find(".video-container")[0],{onSuccess:function(videoid){scope.$apply(function(){console.log("addVideo onSuccess callback"),console.log(videoid),scope.article.video=videoid})},onError:function(data){console.log("addVideo onError callback"),console.log(data)},onProgress:function(data){console.log("addVideo onProgress callback"),console.log(data)}})},scope.clearVideo=function(areYouSure){areYouSure?($("#s3upload-file-input").val(""),scope.article.video=null):$("#confirm-clear-video-modal").modal("show")},scope.abort=function(){return scope.encoding?void abortEncode():void abortUpload()};var initialCheckRan=!1;scope.$watch("video",function(){scope.video&&scope.video.job_id&&!initialCheckRan&&(updateEncodeProgress(),initialCheckRan=!0)})}}}]),angular.module("bulbsCmsApp").directive("mediaRating",["$http","$","routes",function($http,$,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"rating.html",scope:!0,controller:["$scope",function($scope){$scope.search=function(el){$scope.searchTimeout=null;for(var inputs=el.find(".media-field input"),searchParams={},i=0;i'),scope.article.slides[index].id=data.id.toString(),scope.$apply(),$window.picturefill(),$element.find(".image img")[0].complete&&removeLoadingGif())},function(){},function(oldImage){scope.article.slides[index]=oldImage,$window.picturefill()})}}}}]),angular.module("bulbsCmsApp").directive("targeting",["routes",function(routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"targeting.html",link:function(scope){scope.addTargetingRow=function(){scope.targetingArray.push([])},scope.removeTargetingRow=function(index){scope.targetingArray.splice(index,1)}}}}]),angular.module("bulbsCmsApp").directive("titleimage",["$http","$window","$","routes","openImageCropModal",function($http,$window,$,routes,openImageCropModal){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"titleimage.html",scope:{article:"=",image:"="},link:function(scope,element,attrs){$(element);"false"===attrs.caption&&(scope.hideCaption=!0),scope.format=attrs.format||"jpg",scope.crop=attrs.crop||"16x9",scope.placeholderText=attrs.placeholderText||"Optional Image",scope.removeTitleImage=function(){scope.image=null},scope.addTitleImage=function(){$window.uploadImage({onSuccess:function(data){scope.$apply(function(){scope.image={id:data.id.toString(),alt:null,caption:null},setTimeout($window.picturefill,200)})},onError:function(data){scope.$apply(function(){alert("Error: ",data)})},onProgress:function(){}})},scope.editTitleImage=function(){openImageCropModal(scope.image.id).then(function(){$window.picturefill()})}}}}]),angular.module("bulbsCmsApp").filter("truncateByCharacters",function(){return function(input,chars,breakOnWord){if(isNaN(chars))return input;if(0>=chars)return"";if(input&&input.length>=chars){if(input=input.substring(0,chars),breakOnWord)for(;" "===input.charAt(input.length-1);)input=input.substr(0,input.length-1);else{var lastspace=input.lastIndexOf(" ");-1!==lastspace&&(input=input.substr(0,lastspace))}return 1===chars?input+".":input+"..."}return input}}),angular.module("bulbsCmsApp").filter("truncateByWords",function(){return function(input,words){if(isNaN(words))return input;if(0>=words)return"";if(input){var inputWords=input.split(/\s+/);inputWords.length>words&&(input=inputWords.slice(0,words).join(" ")+"...")}return input}}),function(global){var OnionCmsUI=OnionCmsUI||function(editor){function init(){toolbarPosition=$("#content-body .document-tools").offset().top+12,$(window).scroll(function(){window.scrollY>toolbarPosition?$("#content-body .document-tools").addClass("fixed"):$("#content-body .document-tools").removeClass("fixed")}),key("⌘+s, ctrl+s",function(e){e.preventDefault()})}var toolbarPosition;editor.on("init",init)};global.EditorModules.push(OnionCmsUI)}(this),function(global){var OnionImage=OnionImage||function(editor){function uploadImage(options){function onProgress(){}function onSuccess(data){options.onSuccess(options.block,{image_id:data.id}),window.picturefill()}function onError(){}function onCancel(){}global.uploadImage({onProgress:onProgress,onSuccess:onSuccess,onError:onError,onCancel:onCancel})}function editImage(options){current_id=options.element.getAttribute("data-image-id"),openImageCropModal(current_id).then(function(){$(options.element).attr("data-image-id",current_id),window.picturefill()})}editor.on("inline:edit:image",editImage),editor.on("inline:insert:image",uploadImage);var current_id};global.EditorModules.push(OnionImage)}(this),function(global){var OnionVideo=OnionVideo||function(editor){function cleanup(){for(var old_embeds=$("[data-type=embed] iframe[src^='/videos/embed']").parents("div.embed"),i=0;i")}editor.on("inline:insert:hr",insert)};global.EditorModules.push(HR)}(this),$(document).unbind("keydown").bind("keydown",function(event){var doPrevent=!1;if(8===event.keyCode){var d=event.srcElement||event.target;doPrevent=["TEXTAREA","INPUT"].indexOf(-1!==d.tagName.toUpperCase())?d.readOnly||d.disabled:d.isContentEditable?!1:!0}doPrevent&&event.preventDefault()}),angular.module("bulbsCmsApp").service("IfExistsElse",["$window","$http",function(){this.ifExistsElse=function(restQ,propertiesToValues,existsCbk,elseCbk,errorCbk){restQ.then(function(data){for(var resList=data.results||data,j=0;j-1&&(formattedDate+=" "+TIMEZONE_LABEL),formattedDate}}]); \ No newline at end of file +$scope.rating_type&&(new_path+="?rating_type="+$scope.rating_type),$window.location.href=$window.location.origin+new_path}).error(function(){console.log("wow. error."),$("button.go").html(' Error!'),$scope.gotSave=!1})}$scope.gotTags=!1,$scope.gotUser=!1,$scope.gotSave=!1,$scope.$watch(function(){return $scope.gotTags&&$scope.gotUser&&$scope.gotSave},function(val){val&&saveArticle($scope.init)}),$scope.newArticle=function(){var init={title:$scope.newTitle};angular.extend($scope.init,init),$scope.tag?IfExistsElse.ifExistsElse(ContentApi.all("tag").getList({ordering:"name",search:$scope.tag}),{slug:$scope.tag},function(tag){$scope.init.tags=[tag],$scope.gotTags=!0},function(value){console.log("couldnt find tag "+value.slug+" for initial value")},function(data,status){403===status&&Login.showLoginModal()}):$scope.gotTags=!0,IfExistsElse.ifExistsElse(ContentApi.all("user").getList({ordering:"name",search:$window.current_user}),{username:$window.current_user},function(user){$scope.init.authors=[user],$scope.gotUser=!0},function(){console.log("are you bruce willis in sixth sense? dunno.")},function(data,status){403===status&&Login.showLoginModal()}),$scope.gotSave=!0}}],link:function(scope,element){$(element).find("a.create-content").on("click",function(){$("a.create-content.active").removeClass("active"),$(this).addClass("active")}),$(element).find("a.create-content").on("click",function(){return scope.contentTypeLabel=$(this).text(),scope.contentType=$(this).data("content_type")||null,scope.init=$(this).data("init")||{},scope.tag=$(this).data("tag")||null,scope.rating_type=$(this).data("rating_type")||null,scope.$apply(),$(this).hasClass("go-next")&&$("#create button.next-pane").click(),!0}),$("button.next-pane:not(.hide)").on("click",function(){console.log("next clicked"),console.log(scope.contentType),console.log(scope.init),$("#createcontent-01").addClass("hidden"),$("#createcontent-02").removeClass("hidden"),$("button.next-pane:not(.hide)").addClass("hidden"),$(".new-title").focus()}),$(element).find(".new-title").on("keydown",function(e){13===e.keyCode&&$(element).find(".go").click()})}}}]),angular.module("bulbsCmsApp").directive("devicepreview",["$","routes",function($,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"devicepreview.html",link:function(){var pP=$("#page-prev"),tN=pP.find(".nav a"),cO=pP.find(".tab-content .active");tN.click(function(e){var newId=$(this).attr("href").split("#")[1];e.preventDefault(),cO.attr("id",newId)}),$("#page-prev").on("show.bs.collapse",function(){$(this).find(".fa").removeClass("fa-plus-square-o").addClass("fa-minus-square-o")}),$("#page-prev").on("hide.bs.collapse",function(){$(this).find(".fa").removeClass("fa-minus-square-o").addClass("fa-plus-square-o")})}}}]),angular.module("bulbsCmsApp").directive("filterwidget",["$http","$location","$window","$timeout","$","routes",function($http,$location,$window,$timeout,$,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"filterwidget.html",link:function(scope,element){function getAutocompletes(search){return $timeout.cancel(filterInputTimeout),filterInputCounter=0,search.length<1?(scope.autocompleteArray=[],void scope.$apply()):void $http({url:"/cms/api/v1/things/?type=tag&type=feature_type&type=author",method:"GET",params:{q:search}}).success(function(data){scope.autocompleteArray=data})}function arrowSelect(direction){var $toSelect,$entries=$element.find(".entry"),$selected=$element.find(".entry.selected");$selected.length>0?("up"===direction&&($toSelect=$selected.first().prev()),"down"===direction&&($toSelect=$selected.first().next())):("up"===direction&&($toSelect=$entries.last()),"down"===direction&&($toSelect=$entries.first())),scope.selectEntry($toSelect)}function applyFilterChange(filterObject){filterObject.page=1,$location.search(filterObject),scope.getContent(),scope.autocompleteArray=[],$input.trigger("blur")}function getQueryToLabelMappings(type,query){scope.queryToLabelMappings=scope.queryToLabelMappings||{},query in scope.queryToLabelMappings||$http({url:"/cms/api/v1/things/?type="+type,method:"GET",params:{q:query}}).success(function(data){for(var i in data)scope.queryToLabelMappings[data[i].value]=data[i].name})}var $element=$(element),$input=$element.find("input");scope.searchTerm,scope.autocompleteArray=[];var filterInputTimeout,filterInputCounter=0;$input.on("input",function(){var search=$input.val();scope.searchTerm=search,$timeout.cancel(filterInputTimeout),filterInputTimeout=$timeout(function(){getAutocompletes(search)},200),filterInputCounter>2&&getAutocompletes(search)}),$input.on("keyup",function(e){38===e.keyCode&&arrowSelect("up"),40===e.keyCode&&arrowSelect("down"),13===e.keyCode&&($element.find(".selected").length>0?$element.find(".selected").click():scope.addFilter("search",$input.val()))}),$element.find(".search-button").on("click",function(){scope.addFilter("search",$input.val())}),$element.find(".clear-button").on("click",function(){$(this).prev("input").val(""),scope.filterObjects={},applyFilterChange({})}),$element.on("mouseover",".entry",function(){scope.selectEntry(this)}),scope.selectEntry=function(entry){$element.find(".selected").removeClass("selected"),$(entry).addClass("selected")},$input.on("blur",function(){$element.find(".dropdown-menu").fadeOut(200)}),$input.on("focus",function(){$element.find(".dropdown-menu").fadeIn(200)}),scope.addFilter=function(type,newFilterValue){var filterObject=$location.search();"search"===type?filterObject.search=newFilterValue:(filterObject[type]||(filterObject[type]=[]),"string"==typeof filterObject[type]&&(filterObject[type]=[filterObject[type]]),filterObject[type].push(newFilterValue),$input.val("")),applyFilterChange(filterObject),scope.filterInputValue=""},scope.deleteFilter=function(key){var filterObject=$location.search(),toDelete=scope.filterObjects[key];"string"==typeof filterObject[toDelete.type]&&(filterObject[type]=[filterObject[type]]);var toSplice;for(var i in filterObject[toDelete.type])if(filterObject[toDelete.type][i]===toDelete.query){toSplice=i;break}filterObject[toDelete.type].splice(i,1),filterObject.search=$input.val(),delete scope.filterObjects[key],applyFilterChange(filterObject)},scope.$watch("locationSearch",function(search){if(scope.filterObjects={},"undefined"!=typeof search){var filterParamsToTypes={authors:"author",tags:"tag",feature_types:"feature_type"};for(var filterParam in filterParamsToTypes){var filterType=filterParamsToTypes[filterParam];"string"==typeof search[filterParam]&&(search[filterParam]=[search[filterParam]]);for(var i in search[filterParam]){var value=search[filterParam][i];scope.filterObjects[filterType+value]={query:value,type:filterParam},getQueryToLabelMappings(filterType,value)}}search.search&&(scope.filterInputValue=search.search)}}),scope.$on("$routeUpdate",function(){scope.locationSearch=$location.search()}),scope.locationSearch=$location.search()}}}]),angular.module("bulbsCmsApp").directive("imagedrawer",["$http","$window","$","routes","BC_API_KEY",function($http,$window,$,routes,BC_API_KEY){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"imagedrawer.html",scope:{openImageDrawer:"=",closeImageDrawer:"=",article:"="},controller:["$scope",function($scope){function scaleSelection(scale,selection){return[Math.floor(scale*selection[0]),Math.floor(scale*selection[1]),Math.floor(scale*selection[2]),Math.floor(scale*selection[3])]}$scope.current_image={},$scope.$watch("current_image",function(){$scope.library_images=prependCurrentImage($scope.library_images,$scope.current_image)}),$scope.library_images=[];var prependCurrentImage=function(library,current_image){var new_library=library;if(current_image.id){for(var i in new_library)if(new_library[i].id===current_image.id){new_library.splice(i,1);break}new_library.unshift(current_image)}return new_library},refreshImageLibrary=function(params){params=params||{},$http({method:"GET",url:routes.BC_ADMIN_URL+"/api/search",params:params,headers:{"X-Betty-Api-Key":BC_API_KEY}}).success(function(data){$scope.library_images=prependCurrentImage(data.results,$scope.current_image)})};$scope.drawerUpload=function(){$window.uploadImage({onProgress:function(){},onSuccess:function(data){refreshImageLibrary(),$scope.onChangeFn(data),$scope.current_image=data},onError:$scope.onCancelFn,onCancel:$scope.onCancelFn})};var refreshCurrentImage=function(id,field){$http({url:routes.BC_ADMIN_URL+"/api/"+id,method:"GET",headers:{"X-Betty-Api-Key":BC_API_KEY}}).success(function(data){field?$scope.current_image[field]=data[field]:$scope.current_image=data,$window.picturefill(!0)}).error(function(){$scope.current_image={}})};$window.refreshCurrentImage=refreshCurrentImage,$scope.$watch("imageLibrarySearch",function(){refreshImageLibrary({q:$scope.imageLibrarySearch})}),$scope.openImageDrawer=function(){var oldId,onChangeFn,onSaveFn,onCancelFn;"function"==typeof arguments[0]?(oldId=null,onChangeFn=arguments[0],onSaveFn=arguments[1],onCancelFn=arguments[2]):(oldId=arguments[0],onChangeFn=arguments[1],onSaveFn=arguments[2],onCancelFn=arguments[3]),$("#image-drawer").off("click"),$("#image-drawer").on("click","#image-library.image",function(){var id=$(this).data("imageId");refreshCurrentImage(id),onChangeFn(id)}),oldId&&($scope.original_image=oldId),refreshCurrentImage(oldId),$scope.oldId=oldId,$scope.onChangeFn=onChangeFn,$scope.onSaveFn=onSaveFn,$scope.onCancelFn=function(id){$scope.original_image&&refreshCurrentImage($scope.original_image),onCancelFn(id)},$("body").addClass("image-drawer-cropper-open"),refreshImageLibrary()},$window.openImageDrawer=$scope.openImageDrawer,$scope.openImageLibrary=function(){$scope.libraryOpen=!0,$("body").addClass("image-drawer-library-open"),$window.picturefill(!0)},$scope.closeImageDrawer=function(){$("body").removeClass("image-drawer-cropper-open"),$("body").removeClass("image-drawer-library-open"),$window.picturefill()},$scope.closeImageLibrary=function(action){"save"===action&&$scope.onSaveFn(),"cancel"===action&&$scope.onCancelFn($scope.oldId),$("body").removeClass("image-drawer-library-open"),$scope.libraryOpen=!1},$scope.saveImageData=function(e){$window.saveImageData(e)},$scope.saveNewCrop=function(image,ratio){image.selections[ratio]={x0:user_selection_scaled[0],y0:user_selection_scaled[1],x1:user_selection_scaled[2],y1:user_selection_scaled[3]},$scope.$apply(),$window.saveNewCrop(image,ratio,user_selection_scaled,{onSuccess:function(){refreshCurrentImage(image.id,"selections")}})};var jcrop_api,user_selection,user_selection_scaled;$("#cropperModal").on("hidden.bs.modal",function(){jcrop_api.destroy()}),$("#cropperModal").on("shown.bs.modal",function(){$window.picturefill()}),$scope.cropImage=function(image,ratio){var width=500;$("#cropper-img").attr("src",routes.IMAGE_SERVER_URL+"/"+image.id+"/original/"+width+".jpg");var aspectWidth=ratio.split("x")[0],aspectHeight=ratio.split("x")[1],scale=width/image.width,selection=[image.selections[ratio].x0,image.selections[ratio].y0,image.selections[ratio].x1,image.selections[ratio].y1],onSelect=function(c){var selection=[c.x,c.y,c.x2,c.y2];user_selection=selection,user_selection_scaled=scaleSelection(1/scale,selection)};$("#cropper-modal-save-button").unbind("click"),$("#cropper-modal-save-button").click(function(){$scope.saveNewCrop(image,ratio)}),$("#cropperModal").modal("show"),$("#cropper-img").Jcrop({onSelect:onSelect,allowMove:!0,allowResize:!0,aspectRatio:aspectWidth/aspectHeight},function(){jcrop_api=this,jcrop_api.setOptions({aspectRatio:aspectWidth/aspectHeight}),this.focus();scaleSelection(scale,selection);this.setSelect(scaleSelection(scale,selection))})}}],link:function(scope){function preventDefault(e){e=e||window.event,e.preventDefault&&e.preventDefault(),e.returnValue=!1}scope.IMAGE_SERVER_URL=routes.IMAGE_SERVER_URL,document.getElementById("image-cropper").onmousewheel=function(e){document.getElementById("image-cropper").scrollTop-=e.wheelDeltaY,preventDefault(e)},document.getElementById("image-library-body").onmousewheel=function(e){document.getElementById("image-library-body").scrollTop-=e.wheelDeltaY,preventDefault(e)}}}}]),angular.module("bulbsCmsApp").directive("listinput",["$","routes",function($,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"listinput.html",scope:{model:"="},link:function(scope,element,attrs){scope.label=attrs.label,scope.noun=attrs.noun,element.find("input")[0].setAttribute("name",attrs.noun),element.find("input").bind("focus",function(){$(element).find(".preview").hide(),$(element).find(".all-container").show()}),element.find("input").bind("blur",function(){$(element).find(".all-container").hide(),$(element).find(".preview").show()}),element.find("input").bind("keyup",function(e){if(13===e.keyCode){var value=$(this).val();value.length>0&&(scope.model||(scope.model=[]),scope.model.push($(this).val()),scope.$apply(),$(this).val(""))}})}}}]),angular.module("bulbsCmsApp").directive("videoUpload",["$http","$window","$timeout","$sce","$","routes",function($http,$window,$timeout,$sce,$,routes){return{templateUrl:routes.PARTIALS_URL+"mainvideo.html",scope:{article:"="},restrict:"E",link:function(scope,element){function abortUpload(){setProgress(0),scope.req&&scope.req.abort(),scope.video={},setProgress(0)}function abortEncode(){$.ajax("https://app.zencoder.com/api/v2/jobs/"+scope.video.job_id+"/cancel.json?api_key="+$window.videoAttrs.zencoderApiKey,{type:"PUT",success:function(){scope.video.status=3,fakeInput.val("Encoding failed! Please try again.")}})}function setProgress(progress){return 0===progress||100===progress?void progressEl.hide():void((0===scope.lastProgress||Math.abs(progress-scope.lastProgress)>2)&&(progressBar.css("width",Math.floor(progress)+"%"),scope.lastProgress=progress,progressEl.show()))}function updateEncodeProgress(){progressBar.addClass("progress-bar-success"),delete $http.defaults.headers.common["X-Requested-With"],$http({url:"https://app.zencoder.com/api/v2/jobs/"+scope.video.job_id+"/progress.json",method:"GET",params:{api_key:$window.videoAttrs.zencoderApiKey},useXDomain:!0}).success(function(data){"waiting"===data.state||"pending"===data.state||"processing"===data.state?(scope.video.status=2,data.progress>5?(setProgress(data.progress),$timeout(updateEncodeProgress,500)):$timeout(updateEncodeProgress,2e3)):(setProgress(0),"finished"===data.state&&(scope.video.status=1),("failed"===data.state||"cancelled"===data.state)&&(scope.video.status=3,fakeInput.val("Encoding failed! Please try again.")))}).error(function(){$(".alert-danger").fadeIn().delay(1e3).fadeOut()})}console.log("video upload here"),console.log(scope.video_id),scope.$watch("article.video",function(){scope.article.video&&(scope.embedUrl=$sce.trustAsUrl("/videos/embed?id="+scope.article.video),$http({method:"GET",url:"/videos/api/video/"+scope.article.video+"/"}).success(function(data){console.log("getting video from API"),console.log(data),scope.video=data,$window.initVideoWidget(data.id)}))}),scope.$watch("video",function(){});var progressEl=(element.find("label.btn"),element.find("div.progress")),progressBar=element.find("div.progress-bar"),fakeInput=(element.find("div.progress span"),element.find("input.fake-input"));scope.lastProgress=0,scope.addVideo=function(){console.log("chooseFile"),$window.uploadVideo(element.find(".video-container")[0],{onSuccess:function(videoid){scope.$apply(function(){console.log("addVideo onSuccess callback"),console.log(videoid),scope.article.video=videoid})},onError:function(data){console.log("addVideo onError callback"),console.log(data)},onProgress:function(data){console.log("addVideo onProgress callback"),console.log(data)}})},scope.clearVideo=function(areYouSure){areYouSure?($("#s3upload-file-input").val(""),scope.article.video=null):$("#confirm-clear-video-modal").modal("show")},scope.abort=function(){return scope.encoding?void abortEncode():void abortUpload()};var initialCheckRan=!1;scope.$watch("video",function(){scope.video&&scope.video.job_id&&!initialCheckRan&&(updateEncodeProgress(),initialCheckRan=!0)})}}}]),angular.module("bulbsCmsApp").directive("mediaRating",["$http","$","routes",function($http,$,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"rating.html",scope:!0,controller:["$scope",function($scope){$scope.search=function(el){$scope.searchTimeout=null;for(var inputs=el.find(".media-field input"),searchParams={},i=0;i'),scope.article.slides[index].id=data.id.toString(),scope.$apply(),$window.picturefill(),$element.find(".image img")[0].complete&&removeLoadingGif())},function(){},function(oldImage){scope.article.slides[index]=oldImage,$window.picturefill()})}}}}]),angular.module("bulbsCmsApp").directive("targeting",["routes",function(routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"targeting.html",link:function(scope){scope.addTargetingRow=function(){scope.targetingArray.push([])},scope.removeTargetingRow=function(index){scope.targetingArray.splice(index,1)}}}}]),angular.module("bulbsCmsApp").directive("titleimage",["$http","$window","$","routes","openImageCropModal",function($http,$window,$,routes,openImageCropModal){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"titleimage.html",scope:{article:"=",image:"="},link:function(scope,element,attrs){$(element);"false"===attrs.caption&&(scope.hideCaption=!0),scope.format=attrs.format||"jpg",scope.crop=attrs.crop||"16x9",scope.placeholderText=attrs.placeholderText||"Optional Image",scope.removeTitleImage=function(){scope.image=null},scope.addTitleImage=function(){$window.uploadImage({onSuccess:function(data){scope.$apply(function(){scope.image={id:data.id.toString(),alt:null,caption:null},setTimeout($window.picturefill,200)})},onError:function(data){scope.$apply(function(){alert("Error: ",data)})},onProgress:function(){}})},scope.editTitleImage=function(){openImageCropModal(scope.image.id).then(function(){$window.picturefill()})}}}}]),angular.module("bulbsCmsApp").filter("truncateByCharacters",function(){return function(input,chars,breakOnWord){if(isNaN(chars))return input;if(0>=chars)return"";if(input&&input.length>=chars){if(input=input.substring(0,chars),breakOnWord)for(;" "===input.charAt(input.length-1);)input=input.substr(0,input.length-1);else{var lastspace=input.lastIndexOf(" ");-1!==lastspace&&(input=input.substr(0,lastspace))}return 1===chars?input+".":input+"..."}return input}}),angular.module("bulbsCmsApp").filter("truncateByWords",function(){return function(input,words){if(isNaN(words))return input;if(0>=words)return"";if(input){var inputWords=input.split(/\s+/);inputWords.length>words&&(input=inputWords.slice(0,words).join(" ")+"...")}return input}}),function(global){var OnionCmsUI=OnionCmsUI||function(editor){function init(){toolbarPosition=$("#content-body .document-tools").offset().top+12,$(window).scroll(function(){window.scrollY>toolbarPosition?$("#content-body .document-tools").addClass("fixed"):$("#content-body .document-tools").removeClass("fixed")}),key("⌘+s, ctrl+s",function(e){e.preventDefault()})}var toolbarPosition;editor.on("init",init)};global.EditorModules.push(OnionCmsUI)}(this),function(global){var OnionImage=OnionImage||function(editor){function uploadImage(options){function onProgress(){}function onSuccess(data){options.onSuccess(options.block,{image_id:data.id}),window.picturefill()}function onError(){}function onCancel(){}global.uploadImage({onProgress:onProgress,onSuccess:onSuccess,onError:onError,onCancel:onCancel})}function editImage(options){current_id=options.element.getAttribute("data-image-id"),openImageCropModal(current_id).then(function(){$(options.element).attr("data-image-id",current_id),window.picturefill()})}editor.on("inline:edit:image",editImage),editor.on("inline:insert:image",uploadImage);var current_id};global.EditorModules.push(OnionImage)}(this),function(global){var OnionVideo=OnionVideo||function(editor){function cleanup(){for(var old_embeds=$("[data-type=embed] iframe[src^='/videos/embed']").parents("div.embed"),i=0;i")}editor.on("inline:insert:hr",insert)};global.EditorModules.push(HR)}(this),$(document).unbind("keydown").bind("keydown",function(event){var doPrevent=!1;if(8===event.keyCode){var d=event.srcElement||event.target;doPrevent=["TEXTAREA","INPUT"].indexOf(-1!==d.tagName.toUpperCase())?d.readOnly||d.disabled:d.isContentEditable?!1:!0}doPrevent&&event.preventDefault()}),angular.module("bettyCropper",[]).service("bettyCropper",["$http","$interpolate","IMAGE_SERVER_URL","BC_API_KEY",function($http,$interpolate,IMAGE_SERVER_URL,BC_API_KEY){this.detail=function(id){return $http({method:"GET",url:IMAGE_SERVER_URL+"/api/"+id,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},transformRequest:angular.identity})},this.detailPatch=function(id,name,credit,selections){return $http({method:"PATCH",url:IMAGE_SERVER_URL+"/api/"+id,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:{name:name,credit:credit,selections:selections},transformRequest:angular.identity})},this.new=function(image,name,credit){var imageData=new FormData;return imageData.append("image",image),name&&imageData.append("name",name),credit&&imageData.append("credit",credit),$http({method:"POST",url:IMAGE_SERVER_URL+"/api/new",headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:imageData,transformRequest:angular.identity})},this.updateSelection=function(id,ratio,selections){return $http({method:"POST",url:IMAGE_SERVER_URL+"/api/"+id+"/"+ratio,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:selections})},this.url=function(id,crop,width,format){var exp=$interpolate("{{ url }}/{{ id }}/{{ crop }}/{{ width }}.{{ format }}");return exp({url:IMAGE_SERVER_URL,id:id,crop:crop,width:width,format:format})},this.origJpg=function(id,width){return this.url(id,"original",width,"jpg")},this.origGif=function(id,width){return this.url(id,"original",width,"gif")}}]),angular.module("bulbsCmsApp").service("IfExistsElse",["$window","$http",function(){this.ifExistsElse=function(restQ,propertiesToValues,existsCbk,elseCbk,errorCbk){restQ.then(function(data){for(var resList=data.results||data,j=0;j-1&&(formattedDate+=" "+TIMEZONE_LABEL),formattedDate}}]); \ No newline at end of file From 6c8606a9e513a41db804cd1e81898a54596f22b8 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Wed, 30 Apr 2014 10:38:43 -0500 Subject: [PATCH 18/27] wtf? we shouldn't have to do this --- app/index.html | 1 + dist/index.html | 1 + dist/scripts/scripts.js | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/index.html b/app/index.html index d91db16da..d7d5767d9 100644 --- a/app/index.html +++ b/app/index.html @@ -116,6 +116,7 @@ + diff --git a/dist/index.html b/dist/index.html index d91db16da..d7d5767d9 100644 --- a/dist/index.html +++ b/dist/index.html @@ -116,6 +116,7 @@ + diff --git a/dist/scripts/scripts.js b/dist/scripts/scripts.js index d0dce4dc6..42a612c27 100644 --- a/dist/scripts/scripts.js +++ b/dist/scripts/scripts.js @@ -1,2 +1,3 @@ "use strict";angular.module("underscore",[]).value("_",window._),angular.module("NProgress",[]).value("NProgress",window.NProgress),angular.module("URLify",[]).value("URLify",window.URLify),angular.module("jquery",[]).value("$",window.$),angular.module("moment",[]).value("moment",window.moment),angular.module("bulbsCmsApp",["ngCookies","ngResource","ngSanitize","ngRoute","ui.bootstrap","ui.bootstrap.datetimepicker","restangular","bettyCropper","jquery","underscore","NProgress","URLify","moment"]).config(["$locationProvider","$routeProvider","$sceProvider","routes",function($locationProvider,$routeProvider,$sceProvider,routes){$locationProvider.html5Mode(!0),$routeProvider.when("/cms/app/list/:queue/",{templateUrl:routes.PARTIALS_URL+"contentlist.html",controller:"ContentlistCtrl",reloadOnSearch:!1}).when("/cms/app/edit/:id/",{templateUrl:routes.PARTIALS_URL+"contentedit.html",controller:"ContenteditCtrl"}).when("/cms/app/promotion/",{templateUrl:routes.PARTIALS_URL+"promotion.html",controller:"PromotionCtrl",reloadOnSearch:!1}).when("/cms/app/targeting/",{templateUrl:routes.PARTIALS_URL+"targeting-editor.html",controller:"TargetingCtrl"}).when("/cms/app/pzones/",{templateUrl:routes.PARTIALS_URL+"pzones.html",controller:"PzoneCtrl"}).otherwise({redirectTo:"/cms/app/list/published/"}),$sceProvider.enabled(!1)}]).config(["$provide",function($provide){$provide.decorator("$exceptionHandler",function($delegate){return function(exception,cause){$delegate(exception,cause),window.Raven.captureException(exception)}})}]).run(["$rootScope","$http","$cookies",function($rootScope,$http,$cookies){$http.defaults.headers.post["X-CSRFToken"]=$cookies.csrftoken;var deleteHeaders=$http.defaults.headers.delete||{};deleteHeaders["X-CSRFToken"]=$cookies.csrftoken,$http.defaults.headers.delete=deleteHeaders}]),angular.module("bulbsCmsApp").controller("ContentlistCtrl",["$scope","$http","$timeout","$location","$routeParams","$window","$q","$","_","moment","ContentApi",function($scope,$http,$timeout,$location,$routeParams,$window,$q,$,_,moment,ContentApi){function updateIsMyStuff(){if(!$location.search().authors)return void($scope.myStuff=!1);var authors=$location.search().authors;"string"==typeof authors&&(authors=[authors]),$scope.myStuff=1===authors.length&&authors[0]===$window.current_user?!0:!1}$window.document.title="AVCMS | Content",$scope.pageNumber=$location.search().page||"1",$scope.myStuff=!1,$scope.queue=$routeParams.queue||"all",$scope.search=$location.search().search;var getContentCallback=function(data){$scope.articles=data,$scope.totalItems=data.metadata.count};$scope.getContent=function(){var params={page:$scope.pageNumber};"all"!==$scope.queue&&("published"===$scope.queue?params.before=moment().format("YYYY-MM-DDTHH:mmZ"):"waiting"===$scope.queue?params.status="Waiting for Editor":"draft"===$scope.queue?params.status="Draft":"scheduled"===$scope.queue&&(params.after=moment().format("YYYY-MM-DDTHH:mmZ")));var search=$location.search();for(var prop in search)if(search.hasOwnProperty(prop)){var val=search[prop];val&&"false"!==val&&(params[prop]=val)}ContentApi.all("content").getList(params).then(getContentCallback)},updateIsMyStuff(),$scope.getContent(),$scope.$on("$routeUpdate",function(){updateIsMyStuff()}),$scope.$watch("myStuff",function(){$scope.myStuff?$("#meOnly").bootstrapSwitch("setState",!0,!0):$("#meOnly").bootstrapSwitch("setState",!1,!0)}),$("#meOnly").on("switch-change",function(e,data){var value=data.value;value===!0?($location.search().authors=[$window.current_user],$scope.getContent()):value===!1&&(delete $location.search().authors,$scope.getContent())}),$scope.goToPage=function(page){$location.search(_.extend($location.search(),{page:page})),$scope.getContent()},$scope.sort=function(sort){$location.search().ordering&&0===$location.search().ordering.indexOf(sort)&&(sort="-"+sort),$location.search(_.extend($location.search(),{ordering:sort})),$scope.getContent()},$scope.publishSuccessCbk=function(data){var i;for(i=0;i<$scope.articles.length&&$scope.articles[i].id!==data.article.id;i++);for(var field in data.response)$scope.articles[i][field]=data.response[field];return $q.when()},$scope.trashSuccessCbk=function(){$timeout(function(){$scope.getContent(),$("#confirm-trash-modal").modal("hide")},1500)},$(".expcol").click(function(e){e.preventDefault();var nS="1"===$(this).attr("state")?"0":"1",i=nS?"minus":"plus",t=nS?"Collapse":"Expand",tP=$($(this).attr("href")).find(".panel-collapse");tP.collapse("0"===$(this).attr("state")?"show":"hide"),$(this).html(' '+t+" all"),$(this).attr("state",nS)}),$("#meOnly").bootstrapSwitch()}]).directive("ngConfirmClick",[function(){return{link:function(scope,element,attr){var msg=attr.ngConfirmClick||"Are you sure?",clickAction=attr.confirmedClick;element.bind("click",function(){window.confirm(msg)&&scope.$eval(clickAction)})}}}]),angular.module("bulbsCmsApp").controller("ContenteditCtrl",["$scope","$routeParams","$http","$window","$location","$timeout","$compile","$q","$","IfExistsElse","routes","ContentApi","ReviewApi","Login",function($scope,$routeParams,$http,$window,$location,$timeout,$compile,$q,$,IfExistsElse,routes,ContentApi,ReviewApi,Login){function getContent(){return ContentApi.one("content",$routeParams.id).get().then(getArticleCallback)}function mediaItemExistsCbkFactory(index){return function(media_item){$scope.article.ratings[index].media_item=media_item,$scope.mediaItemCallbackCounter-=1}}function mediaItemDoesNotExistCbkFactory(index){return function(){saveMediaItem(index)}}function saveMediaItem(index){var type=$scope.article.ratings[index].type,mediaItem=$scope.article.ratings[index].media_item;mediaItem=ReviewApi.restangularizeElement(null,mediaItem,type);var q;q=mediaItem.id?mediaItem.put():mediaItem.post(),q.then(function(resp){$scope.article.ratings[index].media_item=resp,$scope.mediaItemCallbackCounter-=1}).catch(saveArticleErrorCbk)}function saveToContentApi(){$("#save-article-btn").html(" Saving"),$scope.article.put().then(saveArticleSuccessCbk,saveArticleErrorCbk)}function saveArticleErrorCbk(data){return 403===data.status?(Login.showLoginModal(),void $("#save-article-btn").html("Save")):($("#save-article-btn").html(" Error!"),400===status&&($scope.errors=data),void $scope.saveArticleDeferred.reject())}function saveArticleSuccessCbk(resp){$("#save-article-btn").html(" Saved!"),setTimeout(function(){$("#save-article-btn").html("Save")},1e3),$scope.article=resp,$scope.errors=null,$location.search("rating_type",null),dirtGone(),$scope.saveArticleDeferred.resolve(resp)}function waitForDirt(){$(".edit-page").one("change input","input,div.editor",function(){window.onbeforeunload=function(){return"You have unsaved changes. Leave anyway?"}})}function dirtGone(){window.onbeforeunload=function(){}}$scope.PARTIALS_URL=routes.PARTIALS_URL,$scope.CONTENT_PARTIALS_URL=routes.CONTENT_PARTIALS_URL,$scope.MEDIA_ITEM_PARTIALS_URL=routes.MEDIA_ITEM_PARTIALS_URL,$scope.CACHEBUSTER=routes.CACHEBUSTER;var getArticleCallback=function(data){$window.article=$scope.article=data,!$location.search().rating_type||data.ratings&&0!==data.ratings.length||($scope.article.ratings=[{type:$location.search().rating_type}]),$scope.$watch("article.detail_image.id",function(newVal,oldVal){$scope.article&&(newVal&&oldVal&&newVal===oldVal||null!==newVal&&(!$scope.article.image||!$scope.article.image.id||newVal&&oldVal&&$scope.article.image&&$scope.article.image.id&&oldVal===$scope.article.image.id||!oldVal&&newVal)&&($scope.article.image={id:newVal,alt:null,caption:null}))})};getContent(),$scope.$watch("article.title",function(){$window.document.title="AVCMS | Editing "+($scope.article&&$(""+$scope.article.title+"").text())}),$("body").removeClass(),$scope.tagDisplayFn=function(o){return o.name},$scope.tagCallback=function(o,input,freeForm){var tagVal=freeForm?o:o.name;IfExistsElse.ifExistsElse(ContentApi.all("tag").getList({ordering:"name",search:tagVal}),{name:tagVal},function(tag){$scope.article.tags.push(tag)},function(value){$scope.article.tags.push({name:value.name,type:"content_tag","new":!0})},function(data,status){403===status&&Login.showLoginModal()}),$(input).val("")},$scope.sectionCallback=function(o,input,freeForm){var tagVal=freeForm?o:o.name;IfExistsElse.ifExistsElse(ContentApi.all("tag").getList({ordering:"name",search:tagVal}),{name:tagVal},function(tag){$scope.article.tags.push(tag)},function(){console.log("Can't create sections.")},function(data,status){403===status&&Login.showLoginModal()}),$(input).val("")},$scope.removeTag=function(e){var tag=$(e.target).parents("[data-tag]").data("tag"),id=tag.id,newtags=[];for(var i in $scope.article.tags)$scope.article.tags[i].id!==id&&newtags.push($scope.article.tags[i]);$scope.article.tags=newtags},$scope.removeAuthor=function(e){var author=$(e.target).parents("[data-author]").data("author"),id=author.id,newauthors=[];for(var i in $scope.article.authors)$scope.article.authors[i].id!==id&&newauthors.push($scope.article.authors[i]);$scope.article.authors=newauthors},$scope.featureTypeDisplayFn=function(o){return o.name},$scope.featureTypeCallback=function(o,input,freeForm){var fVal=freeForm?o:o.name;IfExistsElse.ifExistsElse(ContentApi.all("things").getList({type:"feature_type",q:fVal}),{name:fVal},function(ft){$scope.article.feature_type=ft.name,$("#feature-type-container").removeClass("newtag")},function(value){$scope.article.feature_type=value.name,$("#feature-type-container").addClass("newtag")},function(data,status){403===status&&Login.showLoginModal()})},$scope.authorDisplayFn=function(o){return o.first_name&&o.last_name&&o.first_name+" "+o.last_name||"username: "+o.username},$scope.authorCallback=function(o,input){for(var t in $scope.article.authors)if($scope.article.authors[t].id===o.id)return;$scope.article.authors.push(o),$(input).val("")},$scope.saveArticleDeferred=$q.defer(),$scope.mediaItemCallbackCounter=void 0,$scope.$watch("mediaItemCallbackCounter",function(){0===$scope.mediaItemCallbackCounter&&saveToContentApi()}),$scope.saveArticle=function(){var data=$scope.article;$scope.article.title=$scope.editors.content_title_editor.getContent(),"Published"!==$scope.article.status&&($scope.article.slug=$window.URLify($scope.article.title,50)),$scope.article.subhead=$scope.editors.content_subhead_editor.getContent(),$scope.editors.content_body_editor&&($scope.article.body=$scope.editors.content_body_editor.getContent()),$scope.mediaItemCallbackCounter=data.ratings&&data.ratings.length||saveToContentApi();for(var i in data.ratings){var show;if("tvseason"===data.ratings[i].type){var identifier=data.ratings[i].media_item.identifier;show=data.ratings[i].media_item.show,IfExistsElse.ifExistsElse(ReviewApi.all("tvseason").getList({season:identifier,show:show}),{identifier:identifier,show:show},mediaItemExistsCbkFactory(i),mediaItemDoesNotExistCbkFactory(i),saveArticleErrorCbk)}else if("tvepisode"===data.ratings[i].type){show=data.ratings[i].media_item.show;var season=data.ratings[i].media_item.season,episode=data.ratings[i].media_item.episode;IfExistsElse.ifExistsElse(ReviewApi.all("tvepisode").getList({show:show,season:season,episode:episode}),{show:show,season:season,episode:episode},mediaItemExistsCbkFactory(i),mediaItemDoesNotExistCbkFactory(i),saveArticleErrorCbk)}else saveMediaItem(i)}return $scope.saveArticleDeferred.promise},$scope.displayAuthorAutocomplete=function(obj){return obj.first_name+" "+obj.last_name},waitForDirt(),$("#extra-info-modal").on("shown.bs.modal",function(){$window.picturefill()}),$scope.initEditor=function(name,id,options,articleField){$scope.editors=$scope.editors||{},$scope.editors[name]=new window.Editor(options),angular.element(id+" .editor").bind("input",function(){$scope.article[articleField]=$scope.editors[name].getContent()})},$window.initEditor=$scope.initEditor,$scope.$on("$destroy",function(){for(var editor in $scope.editors)$scope.editors[editor].destroy()}),$scope.addRating=function(type){$scope.article.ratings.push({grade:"",type:type,media_item:{type:type}}),$("#add-review-modal").modal("hide")},$scope.deleteRating=function(index){$scope.article.ratings.splice(index,1)},$scope.publishSuccessCbk=function(){return getContent()},$scope.trashSuccessCbk=function(){$timeout(function(){$window.history.back()},1500)}}]),angular.module("bulbsCmsApp").controller("NavCtrl",["$scope","routes",function($scope,routes){$scope.PARTIALS_URL=routes.PARTIALS_URL,$scope.NAV_LOGO=routes.NAV_LOGO}]),angular.module("bulbsCmsApp").controller("PromotionCtrl",["$scope","$http","$window","$","ContentApi","PromotionApi","promo_options",function($scope,$http,$window,$,ContentApi,PromotionApi,promo_options){$window.document.title=promo_options.namespace+" | Promotion Tool",$scope.$watch("pzone",function(pzone){$scope.promotedArticles=pzone&&pzone.content&&pzone.content.length?pzone.content.slice(0):[{hey_checkthis:!0,title:"Nothing Promoted!",feature_type:"Click an article on the right and use 'Insert'"}]}),$scope.getPzones=function(){ContentApi.all("contentlist").getList().then(function(data){$scope.pzones=data,$scope.pzone=data[0]}).catch(function(){alert("Content list does not exist.")})};var getContentCallback=function(data){$scope.articles=data,$scope.totalItems=data.metadata.count};$scope.getContent=function(){ContentApi.all("content").getList({published:!0}).then(getContentCallback)},$scope.$on("$viewContentLoaded",function(){$scope.getPzones(),$scope.getContent()}),$scope.articleIsInPromotedArticles=function(id){if($scope.promotedArticles)for(var i in $scope.promotedArticles)if($scope.promotedArticles[i].id===id)return!0;return!1};var pA=$(".promotion-area"),pC=$(".promotion-container");$scope.insertArticleMode=function(article){$scope.selectedArticle=article,pA.addClass("select-mode"),pC.off("click"),pC.on("click",".promotion-area.select-mode .article-container",function(){var index=$(this).parents("[data-index]").data("index")-0;$scope.insertArticle(index),pA.removeClass("select-mode"),$scope.$apply()})},$scope.insertArticle=function(index){var limit=promo_options.upper_limits[$scope.pzone.name];$scope.promotedArticles[index]&&$scope.promotedArticles[index].id?$scope.promotedArticles.splice(index,0,$scope.selectedArticle):$scope.promotedArticles.splice(index,1,$scope.selectedArticle),limit&&$scope.promotedArticles.length>limit&&$scope.promotedArticles.pop($scope.promotedArticles.length)},$scope.replaceArticleMode=function(article){$scope.selectedArticle=article,pA.addClass("select-mode"),pC.off("click"),pC.on("click",".promotion-area.select-mode .article-container",function(){var index=$(this).parents("[data-index]").data("index");$scope.replaceArticle(index),pA.removeClass("select-mode"),$scope.$apply()})},$scope.replaceArticle=function(index){$scope.promotedArticles.splice(index,1,$scope.selectedArticle)},$scope.save=function(){var items=$scope.promotedArticles.slice(0);items[0].id||items.shift(),$(".save-button").html(' Saving');var payload=$scope.pzone;payload.content=$scope.promotedArticles[0].hey_checkthis?[]:$scope.promotedArticles;var pzone=ContentApi.restangularizeElement(null,payload,"contentlist");pzone.put().then(function(data){$scope.pzone.content=data.content,$(".save-button").removeClass("btn-danger").addClass("btn-success").html(' Saved'),window.setTimeout(function(){$(".save-button").html("Save")},2e3)}).catch(function(){$(".save-button").removeClass("btn-success").addClass("btn-danger").html(' Error'),window.setTimeout(function(){$(".save-button").html("Save")},2e3)})},$scope.moveUp=function(index){if(0!==index){var toMove=$scope.promotedArticles[index];$scope.promotedArticles[index]=$scope.promotedArticles[index-1],$scope.promotedArticles[index-1]=toMove}},$scope.moveDown=function(index){if(index!==$scope.promotedArticles.length-1){var toMove=$scope.promotedArticles[index];$scope.promotedArticles[index]=$scope.promotedArticles[index+1],$scope.promotedArticles[index+1]=toMove}},$scope.remove=function(index){$scope.promotedArticles.splice(index,1)},$("body").on("shown.bs.collapse","#page-prev .collapse",function(){$window.picturefill()})}]),angular.module("bulbsCmsApp").controller("PzoneCtrl",["$scope","$http","$window","$","ContentApi","PromotionApi","routes",function($scope,$http,$window,$,ContentApi,PromotionApi,routes){function getPzone(){PromotionApi.one("pzone/"+$scope.pzoneName).get().then(function(data){$scope.pzone=data}).catch(function(){console.log("Zone does not exist.")})}$window.document.title="AVCMS | Pzone Editor",$scope.pzoneName="homepage-one",$scope.newContentId=null,$scope.$watch("pzoneName",function(){getPzone()}),$scope.typeChanged=function(){console.log("Type changed!"),void 0!==$scope.pzone&&($scope.pzone.data={})};var getContentCallback=function(data){$scope.articles=data,$scope.totalItems=data.metadata.count};$scope.getContent=function(){ContentApi.getList("content").then(getContentCallback)},$scope.getContent(),$scope.getPZoneTemplate=function(){return routes.PARTIALS_URL+"pzones/"+$scope.pzone.zone_type+".html"},$scope.remove=function(contentId){var index=$scope.pzone.data.content_ids.indexOf(contentId);-1!==index&&$scope.pzone.data.content_ids.splice(index,1)},$scope.add=function(prepend){void 0===$scope.pzone.data.content_ids&&($scope.pzone.data.content_ids=[]),prepend&&$scope.newContentIdPrepend?$scope.pzone.data.content_ids.unshift($scope.newContentIdPrepend):$scope.newContentId&&$scope.pzone.data.content_ids.push($scope.newContentId),$scope.newContentId=null,$scope.newContentIdPrepend=null},$scope.save=function(){$("#save-pzone-btn").html(' Saving');var pzone=ContentApi.restangularizeElement(null,$scope.pzone,"pzone/"+$scope.pzoneName);pzone.put().then(function(){$("#save-pzone-btn").html(' Saved!'),window.setTimeout(function(){$("#save-pzone-btn").html("Save")},2e3)}).catch(function(){$("#save-pzone-btn").html(' Saved!'),window.setTimeout(function(){$("#save-pzone-btn").html("Save")},2e3)})}}]),angular.module("bulbsCmsApp").controller("TargetingCtrl",["$scope","$http","$window","$q","$location","tar_options","NProgress",function($scope,$http,$window,$q,$location,tar_options,NProgress){$window.document.title=tar_options.namespace+" | Targeting Editor",NProgress.configure({minimum:.4});var canceller;$scope.search=function(url){url&&("undefined"==typeof canceller?canceller=$q.defer():(canceller.resolve(),NProgress.set(0),canceller=$q.defer()),NProgress.start(),$http({method:"GET",url:tar_options.endpoint,timeout:canceller.promise,params:{url:$scope.url}}).success(function(data){$scope.targetingArray=[];for(var k in data)$scope.targetingArray.push([k,data[k]]);NProgress.done()}).error(function(data,status){404==status&&($scope.targetingArray=[],$scope.targetingArray.push(["",""]),NProgress.done())}))},$scope.save=function(){var data={};for(var i in $scope.targetingArray)data[$scope.targetingArray[i][0]]=$scope.targetingArray[i][1];NProgress.start(),$http({method:"POST",url:tar_options.endpoint+"?url="+$scope.url,data:data}).success(function(){NProgress.done()}).error(function(){NProgress.done()})},$scope.keyHandler=function(event,url){13===event.keyCode?this.search(url):27===event.keyCode&&(event.currentTarget.value="")};var search=$location.search();search&&search.url&&($scope.url=decodeURIComponent(search.url))}]),angular.module("bulbsCmsApp").controller("ContentworkflowCtrl",["$scope","$http","$modal","$window","moment","routes","TIMEZONE_LABEL",function($scope,$http,$modal,$window,moment,routes,TIMEZONE_LABEL){$scope.TIMEZONE_LABEL=TIMEZONE_LABEL,$scope.trashContentModal=function(articleId){return $modal.open({templateUrl:routes.PARTIALS_URL+"modals/confirm-trash-modal.html",controller:"TrashcontentmodalCtrl",scope:$scope,resolve:{articleId:function(){return articleId}}})},$scope.pubTimeModal=function(article){return $modal.open({templateUrl:routes.PARTIALS_URL+"modals/choose-date-modal.html",controller:"PubtimemodalCtrl",scope:$scope,resolve:{article:function(){return article}}})},$scope.sendToEditorModal=function(article){return $modal.open({templateUrl:routes.PARTIALS_URL+"modals/send-to-editor-modal.html",controller:"SendtoeditormodalCtrl",scope:$scope,resolve:{article:function(){return article}}})},$scope.getStatus=function(article){return article&&article.published?moment(article.published)>moment()?"scheduled":"published":"unpublished"}}]),angular.module("bulbsCmsApp").controller("TrashcontentmodalCtrl",["$scope","$http","$modalInstance","$","Login","articleId",function($scope,$http,$modalInstance,$,Login,articleId){console.log("trash content modal ctrl here"),console.log(articleId),$modalInstance.result.then(function(){$("#trash-confirm-button").html("Delete")},function(){$("#trash-confirm-button").html("Delete")}),$scope.trashContent=function(){return console.log("trash content here"),$("#trash-confirm-button").html(' Trashing'),$http({method:"POST",url:"/cms/api/v1/content/"+articleId+"/trash/"}).success(function(){console.log("trash success"),$scope.trashSuccessCbk(),$modalInstance.close()}).error(function(data,status){404===status?($scope.trashSuccessCbk(),$modalInstance.close()):403===status?(Login.showLoginModal(),$modalInstance.dismiss()):$("#trash-confirm-button").html(' Error!')})}}]),angular.module("bulbsCmsApp").controller("PubtimemodalCtrl",["$scope","$http","$modal","$modalInstance","$","moment","Login","routes","article","TIMEZONE_OFFSET",function($scope,$http,$modal,$modalInstance,$,moment,Login,routes,article,TIMEZONE_OFFSET){$scope.article=article,$scope.$watch("pickerValue",function(newVal){var pubTimeMoment=moment(newVal).zone(TIMEZONE_OFFSET);$scope.datePickerValue=moment().year(pubTimeMoment.year()).month(pubTimeMoment.month()).date(pubTimeMoment.date()),$scope.timePickerValue=moment().hour(pubTimeMoment.hour()).minute(pubTimeMoment.minute())}),$modalInstance.result.then(function(){$("#save-pub-time-button").html("Publish")},function(){$("#save-pub-time-button").html("Publish")});var modelDateFormat="YYYY-MM-DDTHH:mmZ";$scope.setTimeShortcut=function(shortcut){if("now"==shortcut){var now=moment().zone(TIMEZONE_OFFSET);$scope.pickerValue=now}if("midnight"==shortcut){var midnight=moment().zone(TIMEZONE_OFFSET).hour(24).minute(0);$scope.pickerValue=midnight}},$scope.setDateShortcut=function(shortcut){var today=moment().zone(TIMEZONE_OFFSET);"today"==shortcut&&($scope.datePickerValue=moment().year(today.year()).month(today.month()).date(today.date())),"tomorrow"==shortcut&&($scope.datePickerValue=moment().year(today.year()).month(today.month()).date(today.date()+1))},$scope.setPubTime=function(){if(!$scope.article.feature_type)return $modalInstance.dismiss(),void $modal.open({templateUrl:routes.PARTIALS_URL+"modals/pubtime-validation-modal.html"});var newDate=moment($scope.datePickerValue),newTime=moment($scope.timePickerValue),newDateTime=moment().zone(TIMEZONE_OFFSET).year(newDate.year()).month(newDate.month()).date(newDate.date()).hour(newTime.hour()).minute(newTime.minute()).format(modelDateFormat),data={published:newDateTime};$("#save-pub-time-button").html(' Saving'),$http({url:"/cms/api/v1/content/"+$scope.article.id+"/publish/",method:"POST",data:data}).success(function(resp){$scope.article.published=resp.published,$scope.publishSuccessCbk&&$scope.publishSuccessCbk({article:$scope.article,response:resp}),$modalInstance.close()}).error(function(error,status){403===status&&Login.showLoginModal(),$modalInstance.dismiss()})},$scope.article.published?$scope.pickerValue=moment($scope.article.published):$scope.setTimeShortcut("now")}]),angular.module("bulbsCmsApp").controller("LoginmodalCtrl",["$scope","Login","$modalInstance","$",function($scope,Login,$modalInstance,$){$scope.login=function(){var username=$("input[name='username']").val(),password=$("input[name='password']").val();Login.login(username,password).then(function(){$modalInstance.close()},function(){$modalInstance.dismiss()})}}]),angular.module("bulbsCmsApp").controller("UnpublishCtrl",["$scope","$http","$q",function($scope,$http,$q){$scope.unpublish=function(article){var data={published:!1},deferred=$q.defer();return $http({url:"/cms/api/v1/content/"+article.id+"/publish/",method:"POST",data:data}).success(function(data){deferred.resolve({article:article,response:data})}).error(function(data){deferred.reject(data)}),deferred.promise}}]),angular.module("bulbsCmsApp").directive("activeNav",["$location",function($location){return{template:'
    • {{label}}
    • ',restrict:"E",scope:{},replace:!0,link:function(scope,element,attrs){scope.href=attrs.href,scope.label=attrs.label,0===$location.path().indexOf(scope.href)&&element.addClass("active")}}}]),angular.module("bulbsCmsApp").directive("articlecontainer",["routes","LOADING_IMG_SRC",function(routes,LOADING_IMG_SRC){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"promotion-tool-article-container.html",scope:{article:"="},link:function(scope,element,attrs){scope.LOADING_IMG_SRC=LOADING_IMG_SRC,scope.ratio=attrs.ratio}}}]),angular.module("bulbsCmsApp").directive("bulbsAutocomplete",["$http","$location","$compile","$timeout","$","Login",function($http,$location,$compile,$timeout,$,Login){return{restrict:"A",scope:!0,link:function(scope,element,attrs){function getAutocompletes(val){$timeout.cancel(inputTimeout),inputCounter=0,$http({method:"GET",url:attrs.resourceUrl+val}).success(function(data){var results=data.results||data;scope.autocomplete_list=results.splice(0,5)}).error(function(data,status){403===status&&Login.showLoginModal()})}scope.displayfn=scope[attrs.displayfn],scope.callback=scope[attrs.callback];var $elem=$(element).find("input");$elem.attr("autocomplete","off");var dropdown=$($compile($("#autocomplete-dropdown-template").html())(scope));$(dropdown).css({position:"absolute",top:$elem.position().top+$elem.outerHeight(),left:$elem.position().left,minWidth:$elem.outerWidth(),display:"none"}),$elem.parent().append(dropdown),$(dropdown).fadeIn("fast"),scope.$watch(function(){return{top:$elem.position().top+$elem.outerHeight(),left:$elem.position().left,minWidth:$elem.outerWidth()}},function(newValue){$(dropdown).css({top:newValue.top,left:newValue.left,minWidth:newValue.minWidth})},!0);var inputTimeout,inputCounter=0;$elem.on("focus",function(){$elem.on("input",function(){var val=$elem.val();""===val?scope.autocomplete_list=[]:($timeout.cancel(inputTimeout),inputTimeout=$timeout(function(){getAutocompletes(val)},200),inputCounter>2&&getAutocompletes(val))}),$(dropdown).fadeIn("fast")}),scope.blurTimeout,$elem.on("blur",function(){$(dropdown).fadeOut("fast")}),$(dropdown).on("mouseover",".entry",function(){$(dropdown).find(".selected").removeClass("selected"),$(this).addClass("selected")}),$elem.on("keyup",function(e){if(40===e.keyCode)if(0===$("div.selected",dropdown).length)$("div.entry",dropdown).first().addClass("selected");else{var curDownSelect=$("div.selected",dropdown),curDownSelectNext=curDownSelect.next("div");0===curDownSelectNext.length?$("div.entry",dropdown).first().addClass("selected"):curDownSelectNext.addClass("selected"),curDownSelect.removeClass("selected")}if(38===e.keyCode)if(0===$("div.selected",dropdown).length)$("div.entry",dropdown).last().addClass("selected");else{var curSelect=$("div.selected",dropdown),curSelectNext=curSelect.prev("div");0===curSelectNext.length?$("div.entry",dropdown).last().addClass("selected"):curSelectNext.addClass("selected"),curSelect.removeClass("selected")}if(13===e.keyCode){var selected=$("div.selected",dropdown);0===selected.length&&scope.onClick($elem.val(),!0),selected.click()}}),scope.onClick=function(o,freeForm){scope.callback(o,$elem,freeForm||!1),scope.autocomplete_list=[]}}}}]),angular.module("bulbsCmsApp").directive("bettyeditable",["$http","routes","BC_API_KEY",function($http,routes){return{replace:!0,restrict:"E",templateUrl:routes.PARTIALS_URL+"bettyeditable.html",scope:{imageId:"=",ratio:"@"},controller:["$scope","$element","$attrs","$http","routes","BC_API_KEY",function($scope,$element,$attrs,$http,routes,BC_API_KEY){$scope.imageData=null,$scope.getImageData=function(){$http({method:"GET",url:routes.IMAGE_SERVER_URL+"/api/"+$scope.imageId,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},transformRequest:angular.identity}).success(function(response){$scope.imageData=response,$scope.showImage()}).error(function(data,status){404===status&&($scope.imageData={width:1200,selections:{"16x9":{x0:0,y0:0,x1:1200,y1:675}}},$scope.showImage())})},$scope.showImage=function(){if(null===$scope.imageData)return console.log("Getting selections!"),void $scope.getImageData();var pictureDiv=$element.find("div")[1],pushdownDiv=$element.find("div")[0];pictureDiv.className="picture";var ratioWidth=parseInt($scope.ratio.split("x")[0],10),ratioHeight=parseInt($scope.ratio.split("x")[1],10);pushdownDiv.style.paddingTop=ratioHeight/ratioWidth*100+"%",pictureDiv.style.backgroundImage="url("+routes.IMAGE_SERVER_URL+"/"+$scope.imageId+"/original/1200.jpg)";var selection=$scope.imageData.selections[$scope.ratio],leftPosition=selection.x0/1200*100,topPosition=selection.y0/(1200*ratioHeight/ratioWidth)*100;pictureDiv.style.backgroundPosition=leftPosition+"% "+topPosition+"%, center",pictureDiv.style.backgroundSize="cover"},$scope.uploadSuccess=function(response){$scope.imageId=response.id,$scope.imageData=response,$scope.showImage()},$scope.upload=function(){if(1!=this.files.length)return void console.log("We need exactly one image!");var file=this.files[0];if(0!=file.type.indexOf("image/"))return void console.log("Not an image!");file.size>68e5&&console.log("The file is too large!");var imageData=new FormData;imageData.append("image",file),$http({method:"POST",url:routes.IMAGE_SERVER_URL+"/api/new",headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:imageData,transformRequest:angular.identity}).success($scope.uploadSuccess)}}],link:function(scope,element){var input=element.find("input");input.on("change",scope.upload);var pictureDiv=element.find("div")[1],pushdownDiv=element.find("div")[0],ratioWidth=parseInt(scope.ratio.split("x")[0],10),ratioHeight=parseInt(scope.ratio.split("x")[1],10);pushdownDiv.style.paddingTop=ratioHeight/ratioWidth*100+"%",scope.imageId?scope.showImage():(pictureDiv.className="picture fa fa-picture-o",element.on("click",function(e){e.stopPropagation(),input[0].click()}))}}}]),angular.module("bulbsCmsApp").directive("bettyimage",["$http","routes",function($http,routes){return{replace:!0,restrict:"E",templateUrl:routes.PARTIALS_URL+"bettyimage.html",scope:{image:"=",ratio:"=",width:"@"},controller:["$scope",function(){}],link:function(scope,element){scope.width=parseInt(scope.width,10);{var ratioWidth=parseInt(scope.ratio.split("x")[0],10),ratioHeight=parseInt(scope.ratio.split("x")[1],10);scope.width*ratioHeight/ratioWidth+"px"}element.css("width",scope.width+"px"),element.css("height",scope.width*ratioHeight/ratioWidth+"px");var selection=scope.image.selections[scope.ratio],selectionWidth=selection.x1-selection.x0,scale=scope.width/selectionWidth,requestWidth=Math.round(scale*(scope.image.width-selectionWidth)+scope.width);element.css("background-image","url("+routes.IMAGE_SERVER_URL+"/"+scope.image.id+"/original/"+requestWidth+".jpg)"),element.css("background-position",scale*selection.x0*-1+"px "+scale*selection.y0*-1+"px")}}}]),angular.module("bulbsCmsApp").directive("createContent",["$http","$window","$","IfExistsElse","Login","ContentApi","routes",function($http,$window,$,IfExistsElse,Login,ContentApi,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"create-content.html",controller:["$scope",function($scope){function saveArticle(){$("button.go").html(' Going'),$http({url:"/cms/api/v1/content/?doctype="+$scope.contentType,method:"POST",data:$scope.init}).success(function(resp){var new_id=resp.id,new_path="/cms/app/edit/"+new_id+"/"; -$scope.rating_type&&(new_path+="?rating_type="+$scope.rating_type),$window.location.href=$window.location.origin+new_path}).error(function(){console.log("wow. error."),$("button.go").html(' Error!'),$scope.gotSave=!1})}$scope.gotTags=!1,$scope.gotUser=!1,$scope.gotSave=!1,$scope.$watch(function(){return $scope.gotTags&&$scope.gotUser&&$scope.gotSave},function(val){val&&saveArticle($scope.init)}),$scope.newArticle=function(){var init={title:$scope.newTitle};angular.extend($scope.init,init),$scope.tag?IfExistsElse.ifExistsElse(ContentApi.all("tag").getList({ordering:"name",search:$scope.tag}),{slug:$scope.tag},function(tag){$scope.init.tags=[tag],$scope.gotTags=!0},function(value){console.log("couldnt find tag "+value.slug+" for initial value")},function(data,status){403===status&&Login.showLoginModal()}):$scope.gotTags=!0,IfExistsElse.ifExistsElse(ContentApi.all("user").getList({ordering:"name",search:$window.current_user}),{username:$window.current_user},function(user){$scope.init.authors=[user],$scope.gotUser=!0},function(){console.log("are you bruce willis in sixth sense? dunno.")},function(data,status){403===status&&Login.showLoginModal()}),$scope.gotSave=!0}}],link:function(scope,element){$(element).find("a.create-content").on("click",function(){$("a.create-content.active").removeClass("active"),$(this).addClass("active")}),$(element).find("a.create-content").on("click",function(){return scope.contentTypeLabel=$(this).text(),scope.contentType=$(this).data("content_type")||null,scope.init=$(this).data("init")||{},scope.tag=$(this).data("tag")||null,scope.rating_type=$(this).data("rating_type")||null,scope.$apply(),$(this).hasClass("go-next")&&$("#create button.next-pane").click(),!0}),$("button.next-pane:not(.hide)").on("click",function(){console.log("next clicked"),console.log(scope.contentType),console.log(scope.init),$("#createcontent-01").addClass("hidden"),$("#createcontent-02").removeClass("hidden"),$("button.next-pane:not(.hide)").addClass("hidden"),$(".new-title").focus()}),$(element).find(".new-title").on("keydown",function(e){13===e.keyCode&&$(element).find(".go").click()})}}}]),angular.module("bulbsCmsApp").directive("devicepreview",["$","routes",function($,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"devicepreview.html",link:function(){var pP=$("#page-prev"),tN=pP.find(".nav a"),cO=pP.find(".tab-content .active");tN.click(function(e){var newId=$(this).attr("href").split("#")[1];e.preventDefault(),cO.attr("id",newId)}),$("#page-prev").on("show.bs.collapse",function(){$(this).find(".fa").removeClass("fa-plus-square-o").addClass("fa-minus-square-o")}),$("#page-prev").on("hide.bs.collapse",function(){$(this).find(".fa").removeClass("fa-minus-square-o").addClass("fa-plus-square-o")})}}}]),angular.module("bulbsCmsApp").directive("filterwidget",["$http","$location","$window","$timeout","$","routes",function($http,$location,$window,$timeout,$,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"filterwidget.html",link:function(scope,element){function getAutocompletes(search){return $timeout.cancel(filterInputTimeout),filterInputCounter=0,search.length<1?(scope.autocompleteArray=[],void scope.$apply()):void $http({url:"/cms/api/v1/things/?type=tag&type=feature_type&type=author",method:"GET",params:{q:search}}).success(function(data){scope.autocompleteArray=data})}function arrowSelect(direction){var $toSelect,$entries=$element.find(".entry"),$selected=$element.find(".entry.selected");$selected.length>0?("up"===direction&&($toSelect=$selected.first().prev()),"down"===direction&&($toSelect=$selected.first().next())):("up"===direction&&($toSelect=$entries.last()),"down"===direction&&($toSelect=$entries.first())),scope.selectEntry($toSelect)}function applyFilterChange(filterObject){filterObject.page=1,$location.search(filterObject),scope.getContent(),scope.autocompleteArray=[],$input.trigger("blur")}function getQueryToLabelMappings(type,query){scope.queryToLabelMappings=scope.queryToLabelMappings||{},query in scope.queryToLabelMappings||$http({url:"/cms/api/v1/things/?type="+type,method:"GET",params:{q:query}}).success(function(data){for(var i in data)scope.queryToLabelMappings[data[i].value]=data[i].name})}var $element=$(element),$input=$element.find("input");scope.searchTerm,scope.autocompleteArray=[];var filterInputTimeout,filterInputCounter=0;$input.on("input",function(){var search=$input.val();scope.searchTerm=search,$timeout.cancel(filterInputTimeout),filterInputTimeout=$timeout(function(){getAutocompletes(search)},200),filterInputCounter>2&&getAutocompletes(search)}),$input.on("keyup",function(e){38===e.keyCode&&arrowSelect("up"),40===e.keyCode&&arrowSelect("down"),13===e.keyCode&&($element.find(".selected").length>0?$element.find(".selected").click():scope.addFilter("search",$input.val()))}),$element.find(".search-button").on("click",function(){scope.addFilter("search",$input.val())}),$element.find(".clear-button").on("click",function(){$(this).prev("input").val(""),scope.filterObjects={},applyFilterChange({})}),$element.on("mouseover",".entry",function(){scope.selectEntry(this)}),scope.selectEntry=function(entry){$element.find(".selected").removeClass("selected"),$(entry).addClass("selected")},$input.on("blur",function(){$element.find(".dropdown-menu").fadeOut(200)}),$input.on("focus",function(){$element.find(".dropdown-menu").fadeIn(200)}),scope.addFilter=function(type,newFilterValue){var filterObject=$location.search();"search"===type?filterObject.search=newFilterValue:(filterObject[type]||(filterObject[type]=[]),"string"==typeof filterObject[type]&&(filterObject[type]=[filterObject[type]]),filterObject[type].push(newFilterValue),$input.val("")),applyFilterChange(filterObject),scope.filterInputValue=""},scope.deleteFilter=function(key){var filterObject=$location.search(),toDelete=scope.filterObjects[key];"string"==typeof filterObject[toDelete.type]&&(filterObject[type]=[filterObject[type]]);var toSplice;for(var i in filterObject[toDelete.type])if(filterObject[toDelete.type][i]===toDelete.query){toSplice=i;break}filterObject[toDelete.type].splice(i,1),filterObject.search=$input.val(),delete scope.filterObjects[key],applyFilterChange(filterObject)},scope.$watch("locationSearch",function(search){if(scope.filterObjects={},"undefined"!=typeof search){var filterParamsToTypes={authors:"author",tags:"tag",feature_types:"feature_type"};for(var filterParam in filterParamsToTypes){var filterType=filterParamsToTypes[filterParam];"string"==typeof search[filterParam]&&(search[filterParam]=[search[filterParam]]);for(var i in search[filterParam]){var value=search[filterParam][i];scope.filterObjects[filterType+value]={query:value,type:filterParam},getQueryToLabelMappings(filterType,value)}}search.search&&(scope.filterInputValue=search.search)}}),scope.$on("$routeUpdate",function(){scope.locationSearch=$location.search()}),scope.locationSearch=$location.search()}}}]),angular.module("bulbsCmsApp").directive("imagedrawer",["$http","$window","$","routes","BC_API_KEY",function($http,$window,$,routes,BC_API_KEY){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"imagedrawer.html",scope:{openImageDrawer:"=",closeImageDrawer:"=",article:"="},controller:["$scope",function($scope){function scaleSelection(scale,selection){return[Math.floor(scale*selection[0]),Math.floor(scale*selection[1]),Math.floor(scale*selection[2]),Math.floor(scale*selection[3])]}$scope.current_image={},$scope.$watch("current_image",function(){$scope.library_images=prependCurrentImage($scope.library_images,$scope.current_image)}),$scope.library_images=[];var prependCurrentImage=function(library,current_image){var new_library=library;if(current_image.id){for(var i in new_library)if(new_library[i].id===current_image.id){new_library.splice(i,1);break}new_library.unshift(current_image)}return new_library},refreshImageLibrary=function(params){params=params||{},$http({method:"GET",url:routes.BC_ADMIN_URL+"/api/search",params:params,headers:{"X-Betty-Api-Key":BC_API_KEY}}).success(function(data){$scope.library_images=prependCurrentImage(data.results,$scope.current_image)})};$scope.drawerUpload=function(){$window.uploadImage({onProgress:function(){},onSuccess:function(data){refreshImageLibrary(),$scope.onChangeFn(data),$scope.current_image=data},onError:$scope.onCancelFn,onCancel:$scope.onCancelFn})};var refreshCurrentImage=function(id,field){$http({url:routes.BC_ADMIN_URL+"/api/"+id,method:"GET",headers:{"X-Betty-Api-Key":BC_API_KEY}}).success(function(data){field?$scope.current_image[field]=data[field]:$scope.current_image=data,$window.picturefill(!0)}).error(function(){$scope.current_image={}})};$window.refreshCurrentImage=refreshCurrentImage,$scope.$watch("imageLibrarySearch",function(){refreshImageLibrary({q:$scope.imageLibrarySearch})}),$scope.openImageDrawer=function(){var oldId,onChangeFn,onSaveFn,onCancelFn;"function"==typeof arguments[0]?(oldId=null,onChangeFn=arguments[0],onSaveFn=arguments[1],onCancelFn=arguments[2]):(oldId=arguments[0],onChangeFn=arguments[1],onSaveFn=arguments[2],onCancelFn=arguments[3]),$("#image-drawer").off("click"),$("#image-drawer").on("click","#image-library.image",function(){var id=$(this).data("imageId");refreshCurrentImage(id),onChangeFn(id)}),oldId&&($scope.original_image=oldId),refreshCurrentImage(oldId),$scope.oldId=oldId,$scope.onChangeFn=onChangeFn,$scope.onSaveFn=onSaveFn,$scope.onCancelFn=function(id){$scope.original_image&&refreshCurrentImage($scope.original_image),onCancelFn(id)},$("body").addClass("image-drawer-cropper-open"),refreshImageLibrary()},$window.openImageDrawer=$scope.openImageDrawer,$scope.openImageLibrary=function(){$scope.libraryOpen=!0,$("body").addClass("image-drawer-library-open"),$window.picturefill(!0)},$scope.closeImageDrawer=function(){$("body").removeClass("image-drawer-cropper-open"),$("body").removeClass("image-drawer-library-open"),$window.picturefill()},$scope.closeImageLibrary=function(action){"save"===action&&$scope.onSaveFn(),"cancel"===action&&$scope.onCancelFn($scope.oldId),$("body").removeClass("image-drawer-library-open"),$scope.libraryOpen=!1},$scope.saveImageData=function(e){$window.saveImageData(e)},$scope.saveNewCrop=function(image,ratio){image.selections[ratio]={x0:user_selection_scaled[0],y0:user_selection_scaled[1],x1:user_selection_scaled[2],y1:user_selection_scaled[3]},$scope.$apply(),$window.saveNewCrop(image,ratio,user_selection_scaled,{onSuccess:function(){refreshCurrentImage(image.id,"selections")}})};var jcrop_api,user_selection,user_selection_scaled;$("#cropperModal").on("hidden.bs.modal",function(){jcrop_api.destroy()}),$("#cropperModal").on("shown.bs.modal",function(){$window.picturefill()}),$scope.cropImage=function(image,ratio){var width=500;$("#cropper-img").attr("src",routes.IMAGE_SERVER_URL+"/"+image.id+"/original/"+width+".jpg");var aspectWidth=ratio.split("x")[0],aspectHeight=ratio.split("x")[1],scale=width/image.width,selection=[image.selections[ratio].x0,image.selections[ratio].y0,image.selections[ratio].x1,image.selections[ratio].y1],onSelect=function(c){var selection=[c.x,c.y,c.x2,c.y2];user_selection=selection,user_selection_scaled=scaleSelection(1/scale,selection)};$("#cropper-modal-save-button").unbind("click"),$("#cropper-modal-save-button").click(function(){$scope.saveNewCrop(image,ratio)}),$("#cropperModal").modal("show"),$("#cropper-img").Jcrop({onSelect:onSelect,allowMove:!0,allowResize:!0,aspectRatio:aspectWidth/aspectHeight},function(){jcrop_api=this,jcrop_api.setOptions({aspectRatio:aspectWidth/aspectHeight}),this.focus();scaleSelection(scale,selection);this.setSelect(scaleSelection(scale,selection))})}}],link:function(scope){function preventDefault(e){e=e||window.event,e.preventDefault&&e.preventDefault(),e.returnValue=!1}scope.IMAGE_SERVER_URL=routes.IMAGE_SERVER_URL,document.getElementById("image-cropper").onmousewheel=function(e){document.getElementById("image-cropper").scrollTop-=e.wheelDeltaY,preventDefault(e)},document.getElementById("image-library-body").onmousewheel=function(e){document.getElementById("image-library-body").scrollTop-=e.wheelDeltaY,preventDefault(e)}}}}]),angular.module("bulbsCmsApp").directive("listinput",["$","routes",function($,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"listinput.html",scope:{model:"="},link:function(scope,element,attrs){scope.label=attrs.label,scope.noun=attrs.noun,element.find("input")[0].setAttribute("name",attrs.noun),element.find("input").bind("focus",function(){$(element).find(".preview").hide(),$(element).find(".all-container").show()}),element.find("input").bind("blur",function(){$(element).find(".all-container").hide(),$(element).find(".preview").show()}),element.find("input").bind("keyup",function(e){if(13===e.keyCode){var value=$(this).val();value.length>0&&(scope.model||(scope.model=[]),scope.model.push($(this).val()),scope.$apply(),$(this).val(""))}})}}}]),angular.module("bulbsCmsApp").directive("videoUpload",["$http","$window","$timeout","$sce","$","routes",function($http,$window,$timeout,$sce,$,routes){return{templateUrl:routes.PARTIALS_URL+"mainvideo.html",scope:{article:"="},restrict:"E",link:function(scope,element){function abortUpload(){setProgress(0),scope.req&&scope.req.abort(),scope.video={},setProgress(0)}function abortEncode(){$.ajax("https://app.zencoder.com/api/v2/jobs/"+scope.video.job_id+"/cancel.json?api_key="+$window.videoAttrs.zencoderApiKey,{type:"PUT",success:function(){scope.video.status=3,fakeInput.val("Encoding failed! Please try again.")}})}function setProgress(progress){return 0===progress||100===progress?void progressEl.hide():void((0===scope.lastProgress||Math.abs(progress-scope.lastProgress)>2)&&(progressBar.css("width",Math.floor(progress)+"%"),scope.lastProgress=progress,progressEl.show()))}function updateEncodeProgress(){progressBar.addClass("progress-bar-success"),delete $http.defaults.headers.common["X-Requested-With"],$http({url:"https://app.zencoder.com/api/v2/jobs/"+scope.video.job_id+"/progress.json",method:"GET",params:{api_key:$window.videoAttrs.zencoderApiKey},useXDomain:!0}).success(function(data){"waiting"===data.state||"pending"===data.state||"processing"===data.state?(scope.video.status=2,data.progress>5?(setProgress(data.progress),$timeout(updateEncodeProgress,500)):$timeout(updateEncodeProgress,2e3)):(setProgress(0),"finished"===data.state&&(scope.video.status=1),("failed"===data.state||"cancelled"===data.state)&&(scope.video.status=3,fakeInput.val("Encoding failed! Please try again.")))}).error(function(){$(".alert-danger").fadeIn().delay(1e3).fadeOut()})}console.log("video upload here"),console.log(scope.video_id),scope.$watch("article.video",function(){scope.article.video&&(scope.embedUrl=$sce.trustAsUrl("/videos/embed?id="+scope.article.video),$http({method:"GET",url:"/videos/api/video/"+scope.article.video+"/"}).success(function(data){console.log("getting video from API"),console.log(data),scope.video=data,$window.initVideoWidget(data.id)}))}),scope.$watch("video",function(){});var progressEl=(element.find("label.btn"),element.find("div.progress")),progressBar=element.find("div.progress-bar"),fakeInput=(element.find("div.progress span"),element.find("input.fake-input"));scope.lastProgress=0,scope.addVideo=function(){console.log("chooseFile"),$window.uploadVideo(element.find(".video-container")[0],{onSuccess:function(videoid){scope.$apply(function(){console.log("addVideo onSuccess callback"),console.log(videoid),scope.article.video=videoid})},onError:function(data){console.log("addVideo onError callback"),console.log(data)},onProgress:function(data){console.log("addVideo onProgress callback"),console.log(data)}})},scope.clearVideo=function(areYouSure){areYouSure?($("#s3upload-file-input").val(""),scope.article.video=null):$("#confirm-clear-video-modal").modal("show")},scope.abort=function(){return scope.encoding?void abortEncode():void abortUpload()};var initialCheckRan=!1;scope.$watch("video",function(){scope.video&&scope.video.job_id&&!initialCheckRan&&(updateEncodeProgress(),initialCheckRan=!0)})}}}]),angular.module("bulbsCmsApp").directive("mediaRating",["$http","$","routes",function($http,$,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"rating.html",scope:!0,controller:["$scope",function($scope){$scope.search=function(el){$scope.searchTimeout=null;for(var inputs=el.find(".media-field input"),searchParams={},i=0;i'),scope.article.slides[index].id=data.id.toString(),scope.$apply(),$window.picturefill(),$element.find(".image img")[0].complete&&removeLoadingGif())},function(){},function(oldImage){scope.article.slides[index]=oldImage,$window.picturefill()})}}}}]),angular.module("bulbsCmsApp").directive("targeting",["routes",function(routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"targeting.html",link:function(scope){scope.addTargetingRow=function(){scope.targetingArray.push([])},scope.removeTargetingRow=function(index){scope.targetingArray.splice(index,1)}}}}]),angular.module("bulbsCmsApp").directive("titleimage",["$http","$window","$","routes","openImageCropModal",function($http,$window,$,routes,openImageCropModal){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"titleimage.html",scope:{article:"=",image:"="},link:function(scope,element,attrs){$(element);"false"===attrs.caption&&(scope.hideCaption=!0),scope.format=attrs.format||"jpg",scope.crop=attrs.crop||"16x9",scope.placeholderText=attrs.placeholderText||"Optional Image",scope.removeTitleImage=function(){scope.image=null},scope.addTitleImage=function(){$window.uploadImage({onSuccess:function(data){scope.$apply(function(){scope.image={id:data.id.toString(),alt:null,caption:null},setTimeout($window.picturefill,200)})},onError:function(data){scope.$apply(function(){alert("Error: ",data)})},onProgress:function(){}})},scope.editTitleImage=function(){openImageCropModal(scope.image.id).then(function(){$window.picturefill()})}}}}]),angular.module("bulbsCmsApp").filter("truncateByCharacters",function(){return function(input,chars,breakOnWord){if(isNaN(chars))return input;if(0>=chars)return"";if(input&&input.length>=chars){if(input=input.substring(0,chars),breakOnWord)for(;" "===input.charAt(input.length-1);)input=input.substr(0,input.length-1);else{var lastspace=input.lastIndexOf(" ");-1!==lastspace&&(input=input.substr(0,lastspace))}return 1===chars?input+".":input+"..."}return input}}),angular.module("bulbsCmsApp").filter("truncateByWords",function(){return function(input,words){if(isNaN(words))return input;if(0>=words)return"";if(input){var inputWords=input.split(/\s+/);inputWords.length>words&&(input=inputWords.slice(0,words).join(" ")+"...")}return input}}),function(global){var OnionCmsUI=OnionCmsUI||function(editor){function init(){toolbarPosition=$("#content-body .document-tools").offset().top+12,$(window).scroll(function(){window.scrollY>toolbarPosition?$("#content-body .document-tools").addClass("fixed"):$("#content-body .document-tools").removeClass("fixed")}),key("⌘+s, ctrl+s",function(e){e.preventDefault()})}var toolbarPosition;editor.on("init",init)};global.EditorModules.push(OnionCmsUI)}(this),function(global){var OnionImage=OnionImage||function(editor){function uploadImage(options){function onProgress(){}function onSuccess(data){options.onSuccess(options.block,{image_id:data.id}),window.picturefill()}function onError(){}function onCancel(){}global.uploadImage({onProgress:onProgress,onSuccess:onSuccess,onError:onError,onCancel:onCancel})}function editImage(options){current_id=options.element.getAttribute("data-image-id"),openImageCropModal(current_id).then(function(){$(options.element).attr("data-image-id",current_id),window.picturefill()})}editor.on("inline:edit:image",editImage),editor.on("inline:insert:image",uploadImage);var current_id};global.EditorModules.push(OnionImage)}(this),function(global){var OnionVideo=OnionVideo||function(editor){function cleanup(){for(var old_embeds=$("[data-type=embed] iframe[src^='/videos/embed']").parents("div.embed"),i=0;i")}editor.on("inline:insert:hr",insert)};global.EditorModules.push(HR)}(this),$(document).unbind("keydown").bind("keydown",function(event){var doPrevent=!1;if(8===event.keyCode){var d=event.srcElement||event.target;doPrevent=["TEXTAREA","INPUT"].indexOf(-1!==d.tagName.toUpperCase())?d.readOnly||d.disabled:d.isContentEditable?!1:!0}doPrevent&&event.preventDefault()}),angular.module("bettyCropper",[]).service("bettyCropper",["$http","$interpolate","IMAGE_SERVER_URL","BC_API_KEY",function($http,$interpolate,IMAGE_SERVER_URL,BC_API_KEY){this.detail=function(id){return $http({method:"GET",url:IMAGE_SERVER_URL+"/api/"+id,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},transformRequest:angular.identity})},this.detailPatch=function(id,name,credit,selections){return $http({method:"PATCH",url:IMAGE_SERVER_URL+"/api/"+id,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:{name:name,credit:credit,selections:selections},transformRequest:angular.identity})},this.new=function(image,name,credit){var imageData=new FormData;return imageData.append("image",image),name&&imageData.append("name",name),credit&&imageData.append("credit",credit),$http({method:"POST",url:IMAGE_SERVER_URL+"/api/new",headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:imageData,transformRequest:angular.identity})},this.updateSelection=function(id,ratio,selections){return $http({method:"POST",url:IMAGE_SERVER_URL+"/api/"+id+"/"+ratio,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:selections})},this.url=function(id,crop,width,format){var exp=$interpolate("{{ url }}/{{ id }}/{{ crop }}/{{ width }}.{{ format }}");return exp({url:IMAGE_SERVER_URL,id:id,crop:crop,width:width,format:format})},this.origJpg=function(id,width){return this.url(id,"original",width,"jpg")},this.origGif=function(id,width){return this.url(id,"original",width,"gif")}}]),angular.module("bulbsCmsApp").service("IfExistsElse",["$window","$http",function(){this.ifExistsElse=function(restQ,propertiesToValues,existsCbk,elseCbk,errorCbk){restQ.then(function(data){for(var resList=data.results||data,j=0;j-1&&(formattedDate+=" "+TIMEZONE_LABEL),formattedDate}}]); \ No newline at end of file +$scope.rating_type&&(new_path+="?rating_type="+$scope.rating_type),$window.location.href=$window.location.origin+new_path}).error(function(){console.log("wow. error."),$("button.go").html(' Error!'),$scope.gotSave=!1})}$scope.gotTags=!1,$scope.gotUser=!1,$scope.gotSave=!1,$scope.$watch(function(){return $scope.gotTags&&$scope.gotUser&&$scope.gotSave},function(val){val&&saveArticle($scope.init)}),$scope.newArticle=function(){var init={title:$scope.newTitle};angular.extend($scope.init,init),$scope.tag?IfExistsElse.ifExistsElse(ContentApi.all("tag").getList({ordering:"name",search:$scope.tag}),{slug:$scope.tag},function(tag){$scope.init.tags=[tag],$scope.gotTags=!0},function(value){console.log("couldnt find tag "+value.slug+" for initial value")},function(data,status){403===status&&Login.showLoginModal()}):$scope.gotTags=!0,IfExistsElse.ifExistsElse(ContentApi.all("user").getList({ordering:"name",search:$window.current_user}),{username:$window.current_user},function(user){$scope.init.authors=[user],$scope.gotUser=!0},function(){console.log("are you bruce willis in sixth sense? dunno.")},function(data,status){403===status&&Login.showLoginModal()}),$scope.gotSave=!0}}],link:function(scope,element){$(element).find("a.create-content").on("click",function(){$("a.create-content.active").removeClass("active"),$(this).addClass("active")}),$(element).find("a.create-content").on("click",function(){return scope.contentTypeLabel=$(this).text(),scope.contentType=$(this).data("content_type")||null,scope.init=$(this).data("init")||{},scope.tag=$(this).data("tag")||null,scope.rating_type=$(this).data("rating_type")||null,scope.$apply(),$(this).hasClass("go-next")&&$("#create button.next-pane").click(),!0}),$("button.next-pane:not(.hide)").on("click",function(){console.log("next clicked"),console.log(scope.contentType),console.log(scope.init),$("#createcontent-01").addClass("hidden"),$("#createcontent-02").removeClass("hidden"),$("button.next-pane:not(.hide)").addClass("hidden"),$(".new-title").focus()}),$(element).find(".new-title").on("keydown",function(e){13===e.keyCode&&$(element).find(".go").click()})}}}]),angular.module("bulbsCmsApp").directive("devicepreview",["$","routes",function($,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"devicepreview.html",link:function(){var pP=$("#page-prev"),tN=pP.find(".nav a"),cO=pP.find(".tab-content .active");tN.click(function(e){var newId=$(this).attr("href").split("#")[1];e.preventDefault(),cO.attr("id",newId)}),$("#page-prev").on("show.bs.collapse",function(){$(this).find(".fa").removeClass("fa-plus-square-o").addClass("fa-minus-square-o")}),$("#page-prev").on("hide.bs.collapse",function(){$(this).find(".fa").removeClass("fa-minus-square-o").addClass("fa-plus-square-o")})}}}]),angular.module("bulbsCmsApp").directive("filterwidget",["$http","$location","$window","$timeout","$","routes",function($http,$location,$window,$timeout,$,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"filterwidget.html",link:function(scope,element){function getAutocompletes(search){return $timeout.cancel(filterInputTimeout),filterInputCounter=0,search.length<1?(scope.autocompleteArray=[],void scope.$apply()):void $http({url:"/cms/api/v1/things/?type=tag&type=feature_type&type=author",method:"GET",params:{q:search}}).success(function(data){scope.autocompleteArray=data})}function arrowSelect(direction){var $toSelect,$entries=$element.find(".entry"),$selected=$element.find(".entry.selected");$selected.length>0?("up"===direction&&($toSelect=$selected.first().prev()),"down"===direction&&($toSelect=$selected.first().next())):("up"===direction&&($toSelect=$entries.last()),"down"===direction&&($toSelect=$entries.first())),scope.selectEntry($toSelect)}function applyFilterChange(filterObject){filterObject.page=1,$location.search(filterObject),scope.getContent(),scope.autocompleteArray=[],$input.trigger("blur")}function getQueryToLabelMappings(type,query){scope.queryToLabelMappings=scope.queryToLabelMappings||{},query in scope.queryToLabelMappings||$http({url:"/cms/api/v1/things/?type="+type,method:"GET",params:{q:query}}).success(function(data){for(var i in data)scope.queryToLabelMappings[data[i].value]=data[i].name})}var $element=$(element),$input=$element.find("input");scope.searchTerm,scope.autocompleteArray=[];var filterInputTimeout,filterInputCounter=0;$input.on("input",function(){var search=$input.val();scope.searchTerm=search,$timeout.cancel(filterInputTimeout),filterInputTimeout=$timeout(function(){getAutocompletes(search)},200),filterInputCounter>2&&getAutocompletes(search)}),$input.on("keyup",function(e){38===e.keyCode&&arrowSelect("up"),40===e.keyCode&&arrowSelect("down"),13===e.keyCode&&($element.find(".selected").length>0?$element.find(".selected").click():scope.addFilter("search",$input.val()))}),$element.find(".search-button").on("click",function(){scope.addFilter("search",$input.val())}),$element.find(".clear-button").on("click",function(){$(this).prev("input").val(""),scope.filterObjects={},applyFilterChange({})}),$element.on("mouseover",".entry",function(){scope.selectEntry(this)}),scope.selectEntry=function(entry){$element.find(".selected").removeClass("selected"),$(entry).addClass("selected")},$input.on("blur",function(){$element.find(".dropdown-menu").fadeOut(200)}),$input.on("focus",function(){$element.find(".dropdown-menu").fadeIn(200)}),scope.addFilter=function(type,newFilterValue){var filterObject=$location.search();"search"===type?filterObject.search=newFilterValue:(filterObject[type]||(filterObject[type]=[]),"string"==typeof filterObject[type]&&(filterObject[type]=[filterObject[type]]),filterObject[type].push(newFilterValue),$input.val("")),applyFilterChange(filterObject),scope.filterInputValue=""},scope.deleteFilter=function(key){var filterObject=$location.search(),toDelete=scope.filterObjects[key];"string"==typeof filterObject[toDelete.type]&&(filterObject[type]=[filterObject[type]]);var toSplice;for(var i in filterObject[toDelete.type])if(filterObject[toDelete.type][i]===toDelete.query){toSplice=i;break}filterObject[toDelete.type].splice(i,1),filterObject.search=$input.val(),delete scope.filterObjects[key],applyFilterChange(filterObject)},scope.$watch("locationSearch",function(search){if(scope.filterObjects={},"undefined"!=typeof search){var filterParamsToTypes={authors:"author",tags:"tag",feature_types:"feature_type"};for(var filterParam in filterParamsToTypes){var filterType=filterParamsToTypes[filterParam];"string"==typeof search[filterParam]&&(search[filterParam]=[search[filterParam]]);for(var i in search[filterParam]){var value=search[filterParam][i];scope.filterObjects[filterType+value]={query:value,type:filterParam},getQueryToLabelMappings(filterType,value)}}search.search&&(scope.filterInputValue=search.search)}}),scope.$on("$routeUpdate",function(){scope.locationSearch=$location.search()}),scope.locationSearch=$location.search()}}}]),angular.module("bulbsCmsApp").directive("imagedrawer",["$http","$window","$","routes","BC_API_KEY",function($http,$window,$,routes,BC_API_KEY){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"imagedrawer.html",scope:{openImageDrawer:"=",closeImageDrawer:"=",article:"="},controller:["$scope",function($scope){function scaleSelection(scale,selection){return[Math.floor(scale*selection[0]),Math.floor(scale*selection[1]),Math.floor(scale*selection[2]),Math.floor(scale*selection[3])]}$scope.current_image={},$scope.$watch("current_image",function(){$scope.library_images=prependCurrentImage($scope.library_images,$scope.current_image)}),$scope.library_images=[];var prependCurrentImage=function(library,current_image){var new_library=library;if(current_image.id){for(var i in new_library)if(new_library[i].id===current_image.id){new_library.splice(i,1);break}new_library.unshift(current_image)}return new_library},refreshImageLibrary=function(params){params=params||{},$http({method:"GET",url:routes.BC_ADMIN_URL+"/api/search",params:params,headers:{"X-Betty-Api-Key":BC_API_KEY}}).success(function(data){$scope.library_images=prependCurrentImage(data.results,$scope.current_image)})};$scope.drawerUpload=function(){$window.uploadImage({onProgress:function(){},onSuccess:function(data){refreshImageLibrary(),$scope.onChangeFn(data),$scope.current_image=data},onError:$scope.onCancelFn,onCancel:$scope.onCancelFn})};var refreshCurrentImage=function(id,field){$http({url:routes.BC_ADMIN_URL+"/api/"+id,method:"GET",headers:{"X-Betty-Api-Key":BC_API_KEY}}).success(function(data){field?$scope.current_image[field]=data[field]:$scope.current_image=data,$window.picturefill(!0)}).error(function(){$scope.current_image={}})};$window.refreshCurrentImage=refreshCurrentImage,$scope.$watch("imageLibrarySearch",function(){refreshImageLibrary({q:$scope.imageLibrarySearch})}),$scope.openImageDrawer=function(){var oldId,onChangeFn,onSaveFn,onCancelFn;"function"==typeof arguments[0]?(oldId=null,onChangeFn=arguments[0],onSaveFn=arguments[1],onCancelFn=arguments[2]):(oldId=arguments[0],onChangeFn=arguments[1],onSaveFn=arguments[2],onCancelFn=arguments[3]),$("#image-drawer").off("click"),$("#image-drawer").on("click","#image-library.image",function(){var id=$(this).data("imageId");refreshCurrentImage(id),onChangeFn(id)}),oldId&&($scope.original_image=oldId),refreshCurrentImage(oldId),$scope.oldId=oldId,$scope.onChangeFn=onChangeFn,$scope.onSaveFn=onSaveFn,$scope.onCancelFn=function(id){$scope.original_image&&refreshCurrentImage($scope.original_image),onCancelFn(id)},$("body").addClass("image-drawer-cropper-open"),refreshImageLibrary()},$window.openImageDrawer=$scope.openImageDrawer,$scope.openImageLibrary=function(){$scope.libraryOpen=!0,$("body").addClass("image-drawer-library-open"),$window.picturefill(!0)},$scope.closeImageDrawer=function(){$("body").removeClass("image-drawer-cropper-open"),$("body").removeClass("image-drawer-library-open"),$window.picturefill()},$scope.closeImageLibrary=function(action){"save"===action&&$scope.onSaveFn(),"cancel"===action&&$scope.onCancelFn($scope.oldId),$("body").removeClass("image-drawer-library-open"),$scope.libraryOpen=!1},$scope.saveImageData=function(e){$window.saveImageData(e)},$scope.saveNewCrop=function(image,ratio){image.selections[ratio]={x0:user_selection_scaled[0],y0:user_selection_scaled[1],x1:user_selection_scaled[2],y1:user_selection_scaled[3]},$scope.$apply(),$window.saveNewCrop(image,ratio,user_selection_scaled,{onSuccess:function(){refreshCurrentImage(image.id,"selections")}})};var jcrop_api,user_selection,user_selection_scaled;$("#cropperModal").on("hidden.bs.modal",function(){jcrop_api.destroy()}),$("#cropperModal").on("shown.bs.modal",function(){$window.picturefill()}),$scope.cropImage=function(image,ratio){var width=500;$("#cropper-img").attr("src",routes.IMAGE_SERVER_URL+"/"+image.id+"/original/"+width+".jpg");var aspectWidth=ratio.split("x")[0],aspectHeight=ratio.split("x")[1],scale=width/image.width,selection=[image.selections[ratio].x0,image.selections[ratio].y0,image.selections[ratio].x1,image.selections[ratio].y1],onSelect=function(c){var selection=[c.x,c.y,c.x2,c.y2];user_selection=selection,user_selection_scaled=scaleSelection(1/scale,selection)};$("#cropper-modal-save-button").unbind("click"),$("#cropper-modal-save-button").click(function(){$scope.saveNewCrop(image,ratio)}),$("#cropperModal").modal("show"),$("#cropper-img").Jcrop({onSelect:onSelect,allowMove:!0,allowResize:!0,aspectRatio:aspectWidth/aspectHeight},function(){jcrop_api=this,jcrop_api.setOptions({aspectRatio:aspectWidth/aspectHeight}),this.focus();scaleSelection(scale,selection);this.setSelect(scaleSelection(scale,selection))})}}],link:function(scope){function preventDefault(e){e=e||window.event,e.preventDefault&&e.preventDefault(),e.returnValue=!1}scope.IMAGE_SERVER_URL=routes.IMAGE_SERVER_URL,document.getElementById("image-cropper").onmousewheel=function(e){document.getElementById("image-cropper").scrollTop-=e.wheelDeltaY,preventDefault(e)},document.getElementById("image-library-body").onmousewheel=function(e){document.getElementById("image-library-body").scrollTop-=e.wheelDeltaY,preventDefault(e)}}}}]),angular.module("bulbsCmsApp").directive("listinput",["$","routes",function($,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"listinput.html",scope:{model:"="},link:function(scope,element,attrs){scope.label=attrs.label,scope.noun=attrs.noun,element.find("input")[0].setAttribute("name",attrs.noun),element.find("input").bind("focus",function(){$(element).find(".preview").hide(),$(element).find(".all-container").show()}),element.find("input").bind("blur",function(){$(element).find(".all-container").hide(),$(element).find(".preview").show()}),element.find("input").bind("keyup",function(e){if(13===e.keyCode){var value=$(this).val();value.length>0&&(scope.model||(scope.model=[]),scope.model.push($(this).val()),scope.$apply(),$(this).val(""))}})}}}]),angular.module("bulbsCmsApp").directive("videoUpload",["$http","$window","$timeout","$sce","$","routes",function($http,$window,$timeout,$sce,$,routes){return{templateUrl:routes.PARTIALS_URL+"mainvideo.html",scope:{article:"="},restrict:"E",link:function(scope,element){function abortUpload(){setProgress(0),scope.req&&scope.req.abort(),scope.video={},setProgress(0)}function abortEncode(){$.ajax("https://app.zencoder.com/api/v2/jobs/"+scope.video.job_id+"/cancel.json?api_key="+$window.videoAttrs.zencoderApiKey,{type:"PUT",success:function(){scope.video.status=3,fakeInput.val("Encoding failed! Please try again.")}})}function setProgress(progress){return 0===progress||100===progress?void progressEl.hide():void((0===scope.lastProgress||Math.abs(progress-scope.lastProgress)>2)&&(progressBar.css("width",Math.floor(progress)+"%"),scope.lastProgress=progress,progressEl.show()))}function updateEncodeProgress(){progressBar.addClass("progress-bar-success"),delete $http.defaults.headers.common["X-Requested-With"],$http({url:"https://app.zencoder.com/api/v2/jobs/"+scope.video.job_id+"/progress.json",method:"GET",params:{api_key:$window.videoAttrs.zencoderApiKey},useXDomain:!0}).success(function(data){"waiting"===data.state||"pending"===data.state||"processing"===data.state?(scope.video.status=2,data.progress>5?(setProgress(data.progress),$timeout(updateEncodeProgress,500)):$timeout(updateEncodeProgress,2e3)):(setProgress(0),"finished"===data.state&&(scope.video.status=1),("failed"===data.state||"cancelled"===data.state)&&(scope.video.status=3,fakeInput.val("Encoding failed! Please try again.")))}).error(function(){$(".alert-danger").fadeIn().delay(1e3).fadeOut()})}console.log("video upload here"),console.log(scope.video_id),scope.$watch("article.video",function(){scope.article.video&&(scope.embedUrl=$sce.trustAsUrl("/videos/embed?id="+scope.article.video),$http({method:"GET",url:"/videos/api/video/"+scope.article.video+"/"}).success(function(data){console.log("getting video from API"),console.log(data),scope.video=data,$window.initVideoWidget(data.id)}))}),scope.$watch("video",function(){});var progressEl=(element.find("label.btn"),element.find("div.progress")),progressBar=element.find("div.progress-bar"),fakeInput=(element.find("div.progress span"),element.find("input.fake-input"));scope.lastProgress=0,scope.addVideo=function(){console.log("chooseFile"),$window.uploadVideo(element.find(".video-container")[0],{onSuccess:function(videoid){scope.$apply(function(){console.log("addVideo onSuccess callback"),console.log(videoid),scope.article.video=videoid})},onError:function(data){console.log("addVideo onError callback"),console.log(data)},onProgress:function(data){console.log("addVideo onProgress callback"),console.log(data)}})},scope.clearVideo=function(areYouSure){areYouSure?($("#s3upload-file-input").val(""),scope.article.video=null):$("#confirm-clear-video-modal").modal("show")},scope.abort=function(){return scope.encoding?void abortEncode():void abortUpload()};var initialCheckRan=!1;scope.$watch("video",function(){scope.video&&scope.video.job_id&&!initialCheckRan&&(updateEncodeProgress(),initialCheckRan=!0)})}}}]),angular.module("bulbsCmsApp").directive("mediaRating",["$http","$","routes",function($http,$,routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"rating.html",scope:!0,controller:["$scope",function($scope){$scope.search=function(el){$scope.searchTimeout=null;for(var inputs=el.find(".media-field input"),searchParams={},i=0;i'),scope.article.slides[index].id=data.id.toString(),scope.$apply(),$window.picturefill(),$element.find(".image img")[0].complete&&removeLoadingGif())},function(){},function(oldImage){scope.article.slides[index]=oldImage,$window.picturefill()})}}}}]),angular.module("bulbsCmsApp").directive("targeting",["routes",function(routes){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"targeting.html",link:function(scope){scope.addTargetingRow=function(){scope.targetingArray.push([])},scope.removeTargetingRow=function(index){scope.targetingArray.splice(index,1)}}}}]),angular.module("bulbsCmsApp").directive("titleimage",["$http","$window","$","routes","openImageCropModal",function($http,$window,$,routes,openImageCropModal){return{restrict:"E",templateUrl:routes.PARTIALS_URL+"titleimage.html",scope:{article:"=",image:"="},link:function(scope,element,attrs){$(element);"false"===attrs.caption&&(scope.hideCaption=!0),scope.format=attrs.format||"jpg",scope.crop=attrs.crop||"16x9",scope.placeholderText=attrs.placeholderText||"Optional Image",scope.removeTitleImage=function(){scope.image=null},scope.addTitleImage=function(){$window.uploadImage({onSuccess:function(data){scope.$apply(function(){scope.image={id:data.id.toString(),alt:null,caption:null},setTimeout($window.picturefill,200)})},onError:function(data){scope.$apply(function(){alert("Error: ",data)})},onProgress:function(){}})},scope.editTitleImage=function(){openImageCropModal(scope.image.id).then(function(){$window.picturefill()})}}}}]),angular.module("bulbsCmsApp").filter("truncateByCharacters",function(){return function(input,chars,breakOnWord){if(isNaN(chars))return input;if(0>=chars)return"";if(input&&input.length>=chars){if(input=input.substring(0,chars),breakOnWord)for(;" "===input.charAt(input.length-1);)input=input.substr(0,input.length-1);else{var lastspace=input.lastIndexOf(" ");-1!==lastspace&&(input=input.substr(0,lastspace))}return 1===chars?input+".":input+"..."}return input}}),angular.module("bulbsCmsApp").filter("truncateByWords",function(){return function(input,words){if(isNaN(words))return input;if(0>=words)return"";if(input){var inputWords=input.split(/\s+/);inputWords.length>words&&(input=inputWords.slice(0,words).join(" ")+"...")}return input}}),function(global){var OnionCmsUI=OnionCmsUI||function(editor){function init(){toolbarPosition=$("#content-body .document-tools").offset().top+12,$(window).scroll(function(){window.scrollY>toolbarPosition?$("#content-body .document-tools").addClass("fixed"):$("#content-body .document-tools").removeClass("fixed")}),key("⌘+s, ctrl+s",function(e){e.preventDefault()})}var toolbarPosition;editor.on("init",init)};global.EditorModules.push(OnionCmsUI)}(this),function(global){var OnionImage=OnionImage||function(editor){function uploadImage(options){function onProgress(){}function onSuccess(data){options.onSuccess(options.block,{image_id:data.id}),window.picturefill()}function onError(){}function onCancel(){}global.uploadImage({onProgress:onProgress,onSuccess:onSuccess,onError:onError,onCancel:onCancel})}function editImage(options){current_id=options.element.getAttribute("data-image-id"),openImageCropModal(current_id).then(function(){$(options.element).attr("data-image-id",current_id),window.picturefill()})}editor.on("inline:edit:image",editImage),editor.on("inline:insert:image",uploadImage);var current_id};global.EditorModules.push(OnionImage)}(this),function(global){var OnionVideo=OnionVideo||function(editor){function cleanup(){for(var old_embeds=$("[data-type=embed] iframe[src^='/videos/embed']").parents("div.embed"),i=0;i")}editor.on("inline:insert:hr",insert)};global.EditorModules.push(HR)}(this),$(document).unbind("keydown").bind("keydown",function(event){var doPrevent=!1;if(8===event.keyCode){var d=event.srcElement||event.target;doPrevent=["TEXTAREA","INPUT"].indexOf(-1!==d.tagName.toUpperCase())?d.readOnly||d.disabled:d.isContentEditable?!1:!0}doPrevent&&event.preventDefault()}),angular.module("bettyCropper",[]).service("bettyCropper",["$http","$interpolate","IMAGE_SERVER_URL","BC_API_KEY",function($http,$interpolate,IMAGE_SERVER_URL,BC_API_KEY){this.detail=function(id){return $http({method:"GET",url:IMAGE_SERVER_URL+"/api/"+id,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},transformRequest:angular.identity})},this.detailPatch=function(id,name,credit,selections){return $http({method:"PATCH",url:IMAGE_SERVER_URL+"/api/"+id,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:{name:name,credit:credit,selections:selections},transformRequest:angular.identity})},this.new=function(image,name,credit){var imageData=new FormData;return imageData.append("image",image),name&&imageData.append("name",name),credit&&imageData.append("credit",credit),$http({method:"POST",url:IMAGE_SERVER_URL+"/api/new",headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:imageData,transformRequest:angular.identity})},this.updateSelection=function(id,ratio,selections){return $http({method:"POST",url:IMAGE_SERVER_URL+"/api/"+id+"/"+ratio,headers:{"X-Betty-Api-Key":BC_API_KEY,"Content-Type":void 0},data:selections})},this.url=function(id,crop,width,format){var exp=$interpolate("{{ url }}/{{ id }}/{{ crop }}/{{ width }}.{{ format }}");return exp({url:IMAGE_SERVER_URL,id:id,crop:crop,width:width,format:format})},this.origJpg=function(id,width){return this.url(id,"original",width,"jpg")},this.origGif=function(id,width){return this.url(id,"original",width,"gif")}}]),angular.module("bulbsCmsApp").service("IfExistsElse",["$window","$http",function(){this.ifExistsElse=function(restQ,propertiesToValues,existsCbk,elseCbk,errorCbk){restQ.then(function(data){for(var resList=data.results||data,j=0;js_width?(h_or_w="height",selection_length=s_height):(h_or_w="width",selection_length=s_width),styles={},scale=thumb[h_or_w]/selection_length,styles.background="url("+$scope.image_url+")",styles["background-size"]=$scope.scaleNumber($scope.image.width,scale)+"px",styles["background-position"]="-"+$scope.scaleNumber(selection.x0,scale)+"px -"+$scope.scaleNumber(selection.y0,scale)+"px",styles["background-repeat"]="no-repeat",styles.height=$scope.scaleNumber(s_height,scale)+"px",styles.width=$scope.scaleNumber(s_width,scale)+"px",styles.top="50%",styles["margin-top"]="-"+$scope.scaleNumber(s_height,scale)/2+"px",styles},$scope.scaleNumber=function(num,by_scale){return Math.floor(num*by_scale)},$scope.cancel=function(){$modalInstance.dismiss("cancel")},$scope.back=function(){$scope.cropMode=!1},$scope.saveAndQuit=function(){$scope.processJcropSelection(jcrop_api.tellSelect()),bettyCropper.update_selection($scope.image.id,$scope.selectedCrop[0],$scope.image.selections[$scope.selectedCrop[0]]).success(function(){$modalInstance.close()})},$scope.saveAndNext=function(){$scope.processJcropSelection(jcrop_api.tellSelect()),bettyCropper.update_selection($scope.image.id,$scope.selectedCrop[0],$scope.image.selections[$scope.selectedCrop[0]]).success(function(){var next=$scope.currentCrop+1; +next>=$scope.ratioOrder.length&&(next=0),$scope.currentCrop=next,$scope.selectedCrop=[$scope.ratioOrder[$scope.currentCrop],$scope.image.selections[$scope.ratioOrder[$scope.currentCrop]]]})},$scope.isCurrentCrop=function(ratio){return $scope.ratioOrder[$scope.currentCrop]===ratio?{color:"#5bc0de"}:void 0},bettyCropper.detail(id).success(function(data){$scope.image=data,$scope.setThumbStyles($scope.image,$scope.image.selections),$scope.ratioOrder=Object.keys($scope.image.selections),$scope.currentCrop=0})};return $modal.open({templateUrl:routes.PARTIALS_URL+"image-crop-modal.html",controller:ModalInstanceCtrl,resolve:{id:function(){return id}}}).result};return $window.openImageCropModal=openImageCropModal,openImageCropModal}]),angular.module("bulbsCmsApp").config(["RestangularProvider","bulbsApiConfig",function(RestangularProvider,bulbsApiConfig){RestangularProvider.setResponseExtractor(function(response,operation){var newResponse=response;return"getList"===operation&&"undefined"!=typeof response.results&&(newResponse=response.results,newResponse.metadata={count:response.count,next:response.next,previous:response.previous}),newResponse}),bulbsApiConfig.requestSuffix&&RestangularProvider.setRequestSuffix(bulbsApiConfig.requestSuffix)}]).constant("bulbsApiConfig",{requestSuffix:"/"}),angular.module("bulbsCmsApp").factory("ContentApi",["Restangular","contentApiConfig",function(Restangular,contentApiConfig){return Restangular.withConfig(function(RestangularConfigurer){RestangularConfigurer.setBaseUrl(contentApiConfig.baseUrl)})}]).constant("contentApiConfig",{baseUrl:"/cms/api/v1"}),angular.module("bulbsCmsApp").factory("ReviewApi",["Restangular","reviewApiConfig",function(Restangular,reviewApiConfig){return Restangular.withConfig(function(RestangularConfigurer){RestangularConfigurer.setBaseUrl(reviewApiConfig.baseUrl)})}]).constant("reviewApiConfig",{baseUrl:"/reviews/api/v1"}),angular.module("bulbsCmsApp").factory("PromotionApi",["Restangular","promotionApiConfig",function(Restangular,promotionApiConfig){return Restangular.withConfig(function(RestangularConfigurer){RestangularConfigurer.setBaseUrl(promotionApiConfig.baseUrl)})}]).constant("promotionApiConfig",{baseUrl:"/promotions/api"}),angular.module("bulbsCmsApp").factory("AdApi",["Restangular","adApiConfig",function(Restangular,adApiConfig){return Restangular.withConfig(function(RestangularConfigurer){RestangularConfigurer.setBaseUrl(adApiConfig.baseUrl)})}]).constant("adApiConfig",{baseUrl:"/ads"}),angular.module("bulbsCmsApp").service("Login",["$rootScope","$http","$cookies","$window","$modal","$","routes",function($rootScope,$http,$cookies,$window,$modal,$,routes){return $rootScope.$watch(function(){return $cookies.csrftoken},function(newCsrf){$http.defaults.headers.post["X-CSRFToken"]=newCsrf,$window.jqueryCsrfSetup&&$window.jqueryCsrfSetup()}),{showLoginModal:function(){return $modal.open({templateUrl:routes.PARTIALS_URL+"modals/login-modal.html",controller:"LoginmodalCtrl"})},login:function(username,password){var data=$.param({username:username,password:password});return $http({method:"POST",url:"/login/",data:data,headers:{"Content-Type":"application/x-www-form-urlencoded"}})}}}]),angular.module("bulbsCmsApp").controller("SendtoeditormodalCtrl",["$scope","$http","$modalInstance","Login","article",function($scope,$http,$modalInstance,Login){$scope.sendToEditor=function(article){$http({url:"/cms/api/v1/content/"+article.id+"/send/",method:"POST",data:{notes:$scope.noteToEditor}}).success(function(data){$scope.publishSuccessCbk({article:article,response:data})}).error(function(error,status){403===status&&Login.showLoginModal(),$modalInstance.dismiss()})}}]),angular.module("bulbsCmsApp").filter("tzDate",["dateFilter","moment","TIMEZONE_OFFSET","TIMEZONE_LABEL",function(dateFilter,moment,TIMEZONE_OFFSET,TIMEZONE_LABEL){return function(input,format){if(!input)return"";var newdate=moment(input).zone(TIMEZONE_OFFSET).format("YYYY-MM-DDTHH:mm"),formattedDate=dateFilter(newdate,format);return format.toLowerCase().indexOf("h")>-1&&(formattedDate+=" "+TIMEZONE_LABEL),formattedDate}}]); \ No newline at end of file From bb721f4983c7d2015516b5964889f690397e7e6d Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Wed, 30 Apr 2014 12:14:59 -0500 Subject: [PATCH 19/27] happy sbloomfield? --- app/scripts/app.js | 2 +- app/scripts/modules/betty-cropper.js | 4 ++-- app/scripts/services/imagecropmodal.js | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/scripts/app.js b/app/scripts/app.js index 48548640b..1c88208cf 100644 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -19,7 +19,7 @@ angular.module('bulbsCmsApp', [ 'ui.bootstrap', 'ui.bootstrap.datetimepicker', 'restangular', - 'bettyCropper', + 'BettyCropper', 'jquery', 'underscore', 'NProgress', diff --git a/app/scripts/modules/betty-cropper.js b/app/scripts/modules/betty-cropper.js index bfc8594ac..829ac36ab 100644 --- a/app/scripts/modules/betty-cropper.js +++ b/app/scripts/modules/betty-cropper.js @@ -1,5 +1,5 @@ -angular.module('bettyCropper', []) - .service('bettyCropper', function bettyCropper($http, $interpolate, IMAGE_SERVER_URL, BC_API_KEY) { +angular.module('BettyCropper', []) + .service('BettyCropper', function BettyCropper($http, $interpolate, IMAGE_SERVER_URL, BC_API_KEY) { /*\ diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/services/imagecropmodal.js index 9c6d358e2..fb686a759 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/services/imagecropmodal.js @@ -3,14 +3,14 @@ angular.module('bulbsCmsApp') .factory('openImageCropModal', function ($window, $document, $compile, $rootScope, $modal, routes) { var openImageCropModal = function (id) { - var ModalInstanceCtrl = function ($scope, $timeout, bettyCropper, $modalInstance, id) { + var ModalInstanceCtrl = function ($scope, $timeout, BettyCropper, $modalInstance, id) { var jcrop_api; $scope.cropMode = false; $scope.thumb = {height:180, width: 180}; $scope.preview_thumb = {height: 110, width: 110}; $scope.crop_image_width = 550; - $scope.image_url = bettyCropper.origJpg(id, $scope.crop_image_width); + $scope.image_url = BettyCropper.origJpg(id, $scope.crop_image_width); $scope.preview_style = {}; var setupCropper = function () { @@ -151,7 +151,7 @@ angular.module('bulbsCmsApp') $scope.saveAndQuit = function () { // Should probably use a save directive here $scope.processJcropSelection(jcrop_api.tellSelect()); - bettyCropper.update_selection( + BettyCropper.update_selection( $scope.image.id, $scope.selectedCrop[0], $scope.image.selections[$scope.selectedCrop[0]] @@ -162,7 +162,7 @@ angular.module('bulbsCmsApp') $scope.saveAndNext = function () { $scope.processJcropSelection(jcrop_api.tellSelect()); - bettyCropper.update_selection( + BettyCropper.update_selection( $scope.image.id, $scope.selectedCrop[0], $scope.image.selections[$scope.selectedCrop[0]] @@ -185,7 +185,7 @@ angular.module('bulbsCmsApp') } }; - bettyCropper.detail(id) + BettyCropper.detail(id) .success(function (data) { $scope.image = data; $scope.setThumbStyles($scope.image, $scope.image.selections); From d07dd480a13142e93daffd30a865d498afc5f8a8 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Thu, 1 May 2014 16:55:29 -0500 Subject: [PATCH 20/27] closes #22, refactors and bug squash, and tests --- app/index.html | 3 + app/mocks/api.js | 147 +++++++- app/scripts/services/imagecropmodal.js | 378 ++++++++++---------- test/config.js | 3 + test/spec/controllers/imagecropmodalctrl.js | 221 ++++++++++++ 5 files changed, 560 insertions(+), 192 deletions(-) create mode 100644 test/spec/controllers/imagecropmodalctrl.js diff --git a/app/index.html b/app/index.html index d7d5767d9..b4b095a04 100644 --- a/app/index.html +++ b/app/index.html @@ -133,6 +133,9 @@ \ No newline at end of file + diff --git a/app/scripts/directives/bettyeditable.js b/app/scripts/directives/bettyeditable.js index cd97f85f6..f00f6872f 100644 --- a/app/scripts/directives/bettyeditable.js +++ b/app/scripts/directives/bettyeditable.js @@ -1,77 +1,29 @@ 'use strict'; angular.module('bulbsCmsApp') - .directive('bettyeditable', function ($http, routes, BC_API_KEY) { + .directive('bettyeditable', function ($http, routes, BettyCropper, openImageCropModal) { return { - replace: true, restrict: 'E', templateUrl: routes.PARTIALS_URL + 'bettyeditable.html', scope: { - 'imageId': '=', + 'image': '=', + 'addStyles': '@', + 'placeholderText': '@', 'ratio': "@" }, - controller: function ($scope, $element, $attrs, $http, routes, BC_API_KEY) { + controller: function ($scope, $element) { $scope.imageData = null; - $scope.getImageData = function() { - $http({ - method: 'GET', - url: routes.IMAGE_SERVER_URL + '/api/' + $scope.imageId, - headers: { - 'X-Betty-Api-Key': BC_API_KEY, - 'Content-Type': undefined - }, - transformRequest: angular.identity - }).success(function(response){ - $scope.imageData = response; - $scope.showImage(); - }).error(function(data, status, headers, config){ - if (status === 404) { - // For placeholder images, we definitely need to figure some better out here. - $scope.imageData = { - "width": 1200, - "selections" : { - "16x9" : { - "x0": 0, - "y0": 0, - "x1": 1200, - "y1": 675 - } - } - } - $scope.showImage(); - } - }); - }; - - $scope.showImage = function(){ - if($scope.imageData === null) { - console.log("Getting selections!"); - $scope.getImageData(); - return; - } - var pictureDiv = $element.find("div")[1]; - var pushdownDiv = $element.find("div")[0]; - pictureDiv.className = "picture"; - - var ratioWidth = parseInt($scope.ratio.split('x')[0], 10); - var ratioHeight = parseInt($scope.ratio.split('x')[1], 10); - - pushdownDiv.style.paddingTop = (ratioHeight / ratioWidth * 100) + "%"; - pictureDiv.style.backgroundImage = 'url(' + routes.IMAGE_SERVER_URL + '/' + $scope.imageId + '/original/' + 1200 + '.jpg)'; - - var selection = $scope.imageData.selections[$scope.ratio]; - - var leftPosition = selection.x0 / 1200 * 100; - var topPosition = selection.y0 / (1200 * ratioHeight / ratioWidth) * 100; - - pictureDiv.style.backgroundPosition = leftPosition + "% " + topPosition + "%, center"; - pictureDiv.style.backgroundSize = "cover"; - } - $scope.uploadSuccess = function(response){ - $scope.imageId = response.id; + if (!$scope.image) { + $scope.image = { + id: null, + caption: null, + alt: null + }; + } + $scope.image.id = response.id; $scope.imageData = response; $scope.showImage(); } @@ -94,40 +46,114 @@ angular.module('bulbsCmsApp') var imageData = new FormData(); imageData.append('image', file); - $http({ - method: 'POST', - url: routes.IMAGE_SERVER_URL + '/api/new', - headers: { - 'X-Betty-Api-Key': BC_API_KEY, - 'Content-Type': undefined - }, - data: imageData, - transformRequest: angular.identity - }).success($scope.uploadSuccess); + BettyCropper.new( + file + ).success($scope.uploadSuccess); }; }, link: function (scope, element, attrs) { - var input = element.find("input"); input.on("change", scope.upload); - var pictureDiv = element.find("div")[1]; - var pushdownDiv = element.find("div")[0]; + var DEFAULT_IMAGE_WIDTH = 1200; var ratioWidth = parseInt(scope.ratio.split('x')[0], 10); var ratioHeight = parseInt(scope.ratio.split('x')[1], 10); - pushdownDiv.style.paddingTop = (ratioHeight / ratioWidth * 100) + "%"; + scope.uploadFile = function () { + input[0].click(); + } - if (scope.imageId) { - scope.showImage(); - } else { - pictureDiv.className = 'picture fa fa-picture-o'; - element.on("click", function(e){ - e.stopPropagation(); - input[0].click(); + scope.showImage = function () { + if (scope.imageData === null) { + console.log("Getting selections!"); + scope.getImageData(); + return; + } + scope.imageStyling = scope.computeImageStyle( + scope.imageData, + scope.imageData.selections[scope.ratio] + ); + + }; + + scope.computeImageStyle = function (image, selection) { + var scale, styles, + el_height = (image.height / image.width) * $(element).parent().width(), + s_width = selection.x1 - selection.x0, + s_height = selection.y1 - selection.y0, + tmp_selection = selection; + + if (!s_width || !s_height) { + /* + If we have bogus selections, make + the crop equal to the whole image + */ + s_width = $(element).parent().width(); + s_height = el_height; + tmp_selection = { + 'x0': 0, + 'y0': 0, + 'x1': s_width, + 'y1': s_height + }; + } + + styles = {}; + scale = $(element).parent().width() / s_width; + styles['background'] = 'url(' + BettyCropper.origJpg(scope.image.id, DEFAULT_IMAGE_WIDTH) + ')'; + styles['background-size'] = scope.scaleNumber(image.width, scale) + 'px'; + styles['background-position'] = '' + + '-' + scope.scaleNumber(tmp_selection.x0, scale) + 'px ' + + '-' + scope.scaleNumber(tmp_selection.y0, scale) + 'px'; + styles['background-repeat'] = 'no-repeat'; + styles['height'] = scope.scaleNumber(s_height, scale) + 'px'; + // styles['width'] = scope.scaleNumber(s_width, scale) + 'px'; + styles['position'] = 'relative'; + + return styles; + }; + + scope.scaleNumber = function (num, by_scale) { + return Math.floor(num * by_scale); + }; + + scope.getImageData = function () { + BettyCropper.detail( + scope.image.id + ).success(function (response) { + scope.imageData = response; + scope.showImage(); + }).error(function(data, status, headers, config){ + if (status === 404) { + var el_Height = (ratioHeight / ratioWidth) * $(element).parent().width(); + scope.imageStyling = { + 'background': 'url(' + BettyCropper.url( + scope.image.id, scope.ratio, DEFAULT_IMAGE_WIDTH, 'jpg' + ) + ')', + 'background-size': $(element).parent().width(), + 'height': Math.floor(el_Height) + 'px', + 'position': 'relative' + }; + } }); + }; + + scope.removeImage = function () { + scope.image = null; + }; + + scope.editImage = function () { + openImageCropModal(scope.image.id) + .then(function () { + scope.getImageData(); + }) } + + if (scope.image) { + scope.showImage(); + } + } }; - }); \ No newline at end of file + }); diff --git a/app/views/add-image.html b/app/views/add-image.html deleted file mode 100644 index b9eca4f31..000000000 --- a/app/views/add-image.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/views/bettyeditable.html b/app/views/bettyeditable.html index 4efba87e2..89bf88aed 100644 --- a/app/views/bettyeditable.html +++ b/app/views/bettyeditable.html @@ -1,5 +1,21 @@ -
      -
      -
      +
      \ No newline at end of file + +
      +
      +
      +
      +
      +
      +
      +
      + + +
      +
      + + +
      +
      +
      +
      diff --git a/app/views/slideshow-pane.html b/app/views/slideshow-pane.html deleted file mode 100644 index 81dd533a0..000000000 --- a/app/views/slideshow-pane.html +++ /dev/null @@ -1,23 +0,0 @@ -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - - -
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      DirectiveHowSourceRendered
      ng-bind-htmlAutomatically uses $sanitize
      <div ng-bind-html="snippet">
      </div>
      ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value -
      <div ng-bind-html="deliberatelyTrustDangerousSnippet()">
      -</div>
      -
      ng-bindAutomatically escapes
      <div ng-bind="snippet">
      </div>
      -
      - - - it('should sanitize the html snippet by default', function() { - expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). - toBe('

      an html\nclick here\nsnippet

      '); - }); - - it('should inline raw snippet if bound to a trusted value', function() { - expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()). - toBe("

      an html\n" + - "click here\n" + - "snippet

      "); - }); - - it('should escape snippet without any filter', function() { - expect(element(by.css('#bind-default div')).getInnerHtml()). - toBe("<p style=\"color:blue\">an html\n" + - "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + - "snippet</p>"); - }); - - it('should update', function() { - element(by.model('snippet')).clear(); - element(by.model('snippet')).sendKeys('new text'); - expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). - toBe('new text'); - expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe( - 'new text'); - expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( - "new <b onclick=\"alert(1)\">text</b>"); - }); -
      - - */ -function $SanitizeProvider() { - this.$get = ['$$sanitizeUri', function($$sanitizeUri) { - return function(html) { - var buf = []; - htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { - return !/^unsafe/.test($$sanitizeUri(uri, isImage)); - })); - return buf.join(''); - }; - }]; -} - -function sanitizeText(chars) { - var buf = []; - var writer = htmlSanitizeWriter(buf, angular.noop); - writer.chars(chars); - return buf.join(''); -} - - -// Regular Expressions for parsing tags and attributes -var START_TAG_REGEXP = - /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, - END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, - ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, - BEGIN_TAG_REGEXP = /^/g, - DOCTYPE_REGEXP = /]*?)>/i, - CDATA_REGEXP = //g, - // Match everything outside of normal chars and " (quote character) - NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; - - -// Good source of info about elements and attributes -// http://dev.w3.org/html5/spec/Overview.html#semantics -// http://simon.html5.org/html-elements - -// Safe Void Elements - HTML5 -// http://dev.w3.org/html5/spec/Overview.html#void-elements -var voidElements = makeMap("area,br,col,hr,img,wbr"); - -// Elements that you can, intentionally, leave open (and which close themselves) -// http://dev.w3.org/html5/spec/Overview.html#optional-tags -var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), - optionalEndTagInlineElements = makeMap("rp,rt"), - optionalEndTagElements = angular.extend({}, - optionalEndTagInlineElements, - optionalEndTagBlockElements); - -// Safe Block Elements - HTML5 -var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + - "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + - "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); - -// Inline Elements - HTML5 -var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + - "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + - "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); - - -// Special Elements (can contain anything) -var specialElements = makeMap("script,style"); - -var validElements = angular.extend({}, - voidElements, - blockElements, - inlineElements, - optionalEndTagElements); - -//Attributes that have href and hence need to be sanitized -var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); -var validAttrs = angular.extend({}, uriAttrs, makeMap( - 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ - 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ - 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ - 'scope,scrolling,shape,size,span,start,summary,target,title,type,'+ - 'valign,value,vspace,width')); - -function makeMap(str) { - var obj = {}, items = str.split(','), i; - for (i = 0; i < items.length; i++) obj[items[i]] = true; - return obj; -} - - -/** - * @example - * htmlParser(htmlString, { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * }); - * - * @param {string} html string - * @param {object} handler - */ -function htmlParser( html, handler ) { - var index, chars, match, stack = [], last = html; - stack.last = function() { return stack[ stack.length - 1 ]; }; - - while ( html ) { - chars = true; - - // Make sure we're not in a script or style element - if ( !stack.last() || !specialElements[ stack.last() ] ) { - - // Comment - if ( html.indexOf("", index) === index) { - if (handler.comment) handler.comment( html.substring( 4, index ) ); - html = html.substring( index + 3 ); - chars = false; - } - // DOCTYPE - } else if ( DOCTYPE_REGEXP.test(html) ) { - match = html.match( DOCTYPE_REGEXP ); - - if ( match ) { - html = html.replace( match[0], ''); - chars = false; - } - // end tag - } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { - match = html.match( END_TAG_REGEXP ); - - if ( match ) { - html = html.substring( match[0].length ); - match[0].replace( END_TAG_REGEXP, parseEndTag ); - chars = false; - } - - // start tag - } else if ( BEGIN_TAG_REGEXP.test(html) ) { - match = html.match( START_TAG_REGEXP ); - - if ( match ) { - html = html.substring( match[0].length ); - match[0].replace( START_TAG_REGEXP, parseStartTag ); - chars = false; - } - } - - if ( chars ) { - index = html.indexOf("<"); - - var text = index < 0 ? html : html.substring( 0, index ); - html = index < 0 ? "" : html.substring( index ); - - if (handler.chars) handler.chars( decodeEntities(text) ); - } - - } else { - html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), - function(all, text){ - text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); - - if (handler.chars) handler.chars( decodeEntities(text) ); - - return ""; - }); - - parseEndTag( "", stack.last() ); - } - - if ( html == last ) { - throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + - "of html: {0}", html); - } - last = html; - } - - // Clean up any remaining tags - parseEndTag(); - - function parseStartTag( tag, tagName, rest, unary ) { - tagName = angular.lowercase(tagName); - if ( blockElements[ tagName ] ) { - while ( stack.last() && inlineElements[ stack.last() ] ) { - parseEndTag( "", stack.last() ); - } - } - - if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { - parseEndTag( "", tagName ); - } - - unary = voidElements[ tagName ] || !!unary; - - if ( !unary ) - stack.push( tagName ); - - var attrs = {}; - - rest.replace(ATTR_REGEXP, - function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { - var value = doubleQuotedValue - || singleQuotedValue - || unquotedValue - || ''; - - attrs[name] = decodeEntities(value); - }); - if (handler.start) handler.start( tagName, attrs, unary ); - } - - function parseEndTag( tag, tagName ) { - var pos = 0, i; - tagName = angular.lowercase(tagName); - if ( tagName ) - // Find the closest opened tag of the same type - for ( pos = stack.length - 1; pos >= 0; pos-- ) - if ( stack[ pos ] == tagName ) - break; - - if ( pos >= 0 ) { - // Close all the open elements, up the stack - for ( i = stack.length - 1; i >= pos; i-- ) - if (handler.end) handler.end( stack[ i ] ); - - // Remove the open elements from the stack - stack.length = pos; - } - } -} - -var hiddenPre=document.createElement("pre"); -var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; -/** - * decodes all entities into regular string - * @param value - * @returns {string} A string with decoded entities. - */ -function decodeEntities(value) { - if (!value) { return ''; } - - // Note: IE8 does not preserve spaces at the start/end of innerHTML - // so we must capture them and reattach them afterward - var parts = spaceRe.exec(value); - var spaceBefore = parts[1]; - var spaceAfter = parts[3]; - var content = parts[2]; - if (content) { - hiddenPre.innerHTML=content.replace(//g, '>'); -} - -/** - * create an HTML/XML writer which writes to buffer - * @param {Array} buf use buf.jain('') to get out sanitized html string - * @returns {object} in the form of { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * } - */ -function htmlSanitizeWriter(buf, uriValidator){ - var ignore = false; - var out = angular.bind(buf, buf.push); - return { - start: function(tag, attrs, unary){ - tag = angular.lowercase(tag); - if (!ignore && specialElements[tag]) { - ignore = tag; - } - if (!ignore && validElements[tag] === true) { - out('<'); - out(tag); - angular.forEach(attrs, function(value, key){ - var lkey=angular.lowercase(key); - var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); - if (validAttrs[lkey] === true && - (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { - out(' '); - out(key); - out('="'); - out(encodeEntities(value)); - out('"'); - } - }); - out(unary ? '/>' : '>'); - } - }, - end: function(tag){ - tag = angular.lowercase(tag); - if (!ignore && validElements[tag] === true) { - out(''); - } - if (tag == ignore) { - ignore = false; - } - }, - chars: function(chars){ - if (!ignore) { - out(encodeEntities(chars)); - } - } - }; -} - - -// define ngSanitize module and register $sanitize service -angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); - -/* global sanitizeText: false */ - -/** - * @ngdoc filter - * @name linky - * @function - * - * @description - * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and - * plain email address links. - * - * Requires the {@link ngSanitize `ngSanitize`} module to be installed. - * - * @param {string} text Input text. - * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. - * @returns {string} Html-linkified text. - * - * @usage - - * - * @example - - - -
      - Snippet: - - - - - - - - - - - - - - - - - - - - - -
      FilterSourceRendered
      linky filter -
      <div ng-bind-html="snippet | linky">
      </div>
      -
      -
      -
      linky target -
      <div ng-bind-html="snippetWithTarget | linky:'_blank'">
      </div>
      -
      -
      -
      no filter
      <div ng-bind="snippet">
      </div>
      - - - it('should linkify the snippet with urls', function() { - expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). - toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' + - 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); - expect(element.all(by.css('#linky-filter a')).count()).toEqual(4); - }); - - it('should not linkify snippet without the linky filter', function() { - expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()). - toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' + - 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); - expect(element.all(by.css('#escaped-html a')).count()).toEqual(0); - }); - - it('should update', function() { - element(by.model('snippet')).clear(); - element(by.model('snippet')).sendKeys('new http://link.'); - expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). - toBe('new http://link.'); - expect(element.all(by.css('#linky-filter a')).count()).toEqual(1); - expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()) - .toBe('new http://link.'); - }); - - it('should work with the target property', function() { - expect(element(by.id('linky-target')). - element(by.binding("snippetWithTarget | linky:'_blank'")).getText()). - toBe('http://angularjs.org/'); - expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank'); - }); - - - */ -angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { - var LINKY_URL_REGEXP = - /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/, - MAILTO_REGEXP = /^mailto:/; - - return function(text, target) { - if (!text) return text; - var match; - var raw = text; - var html = []; - var url; - var i; - while ((match = raw.match(LINKY_URL_REGEXP))) { - // We can not end in these as they are sometimes found at the end of the sentence - url = match[0]; - // if we did not match ftp/http/mailto then assume mailto - if (match[2] == match[3]) url = 'mailto:' + url; - i = match.index; - addText(raw.substr(0, i)); - addLink(url, match[0].replace(MAILTO_REGEXP, '')); - raw = raw.substring(i + match[0].length); - } - addText(raw); - return $sanitize(html.join('')); - - function addText(text) { - if (!text) { - return; - } - html.push(sanitizeText(text)); - } - - function addLink(url, text) { - html.push(''); - addText(text); - html.push(''); - } - }; -}]); - - -})(window, window.angular); diff --git a/dist/bower_components/angular-sanitize/angular-sanitize.min.js b/dist/bower_components/angular-sanitize/angular-sanitize.min.js deleted file mode 100644 index 08964713b..000000000 --- a/dist/bower_components/angular-sanitize/angular-sanitize.min.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - AngularJS v1.2.16 - (c) 2010-2014 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(p,h,q){'use strict';function E(a){var e=[];s(e,h.noop).chars(a);return e.join("")}function k(a){var e={};a=a.split(",");var d;for(d=0;d=c;d--)e.end&&e.end(f[d]);f.length=c}}var b,g,f=[],l=a;for(f.last=function(){return f[f.length-1]};a;){g=!0;if(f.last()&&x[f.last()])a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(b,a){a=a.replace(H,"$1").replace(I,"$1");e.chars&&e.chars(r(a));return""}),c("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(e.comment&&e.comment(a.substring(4,b)),a=a.substring(b+3),g=!1);else if(y.test(a)){if(b=a.match(y))a= -a.replace(b[0],""),g=!1}else if(J.test(a)){if(b=a.match(z))a=a.substring(b[0].length),b[0].replace(z,c),g=!1}else K.test(a)&&(b=a.match(A))&&(a=a.substring(b[0].length),b[0].replace(A,d),g=!1);g&&(b=a.indexOf("<"),g=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),e.chars&&e.chars(r(g)))}if(a==l)throw L("badparse",a);l=a}c()}function r(a){if(!a)return"";var e=M.exec(a);a=e[1];var d=e[3];if(e=e[2])n.innerHTML=e.replace(//g,">")}function s(a,e){var d=!1,c=h.bind(a,a.push);return{start:function(a,g,f){a=h.lowercase(a);!d&&x[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(g,function(d,f){var g=h.lowercase(f),k="img"===a&&"src"===g||"background"===g;!0!==O[g]||!0===D[g]&&!e(d,k)||(c(" "),c(f),c('="'),c(B(d)),c('"'))}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c(""));a==d&&(d=!1)},chars:function(a){d|| -c(B(a))}}}var L=h.$$minErr("$sanitize"),A=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,z=/^<\s*\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^]*?)>/i,I=/]/,d=/^mailto:/;return function(c,b){function g(a){a&&m.push(E(a))}function f(a,c){m.push("');g(c);m.push("")}if(!c)return c;for(var l,k=c,m=[],n,p;l=k.match(e);)n=l[0],l[2]==l[3]&&(n="mailto:"+n),p=l.index,g(k.substr(0,p)),f(n,l[0].replace(d,"")),k=k.substring(p+l[0].length);g(k);return a(m.join(""))}}])})(window,window.angular); -//# sourceMappingURL=angular-sanitize.min.js.map diff --git a/dist/bower_components/angular-sanitize/angular-sanitize.min.js.map b/dist/bower_components/angular-sanitize/angular-sanitize.min.js.map deleted file mode 100644 index dbf6b259b..000000000 --- a/dist/bower_components/angular-sanitize/angular-sanitize.min.js.map +++ /dev/null @@ -1,8 +0,0 @@ -{ -"version":3, -"file":"angular-sanitize.min.js", -"lineCount":13, -"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAiJtCC,QAASA,EAAY,CAACC,CAAD,CAAQ,CAC3B,IAAIC,EAAM,EACGC,EAAAC,CAAmBF,CAAnBE,CAAwBN,CAAAO,KAAxBD,CACbH,MAAA,CAAaA,CAAb,CACA,OAAOC,EAAAI,KAAA,CAAS,EAAT,CAJoB,CAmE7BC,QAASA,EAAO,CAACC,CAAD,CAAM,CAAA,IAChBC,EAAM,EAAIC,EAAAA,CAAQF,CAAAG,MAAA,CAAU,GAAV,CAAtB,KAAsCC,CACtC,KAAKA,CAAL,CAAS,CAAT,CAAYA,CAAZ,CAAgBF,CAAAG,OAAhB,CAA8BD,CAAA,EAA9B,CAAmCH,CAAA,CAAIC,CAAA,CAAME,CAAN,CAAJ,CAAA,CAAgB,CAAA,CACnD,OAAOH,EAHa,CAmBtBK,QAASA,EAAU,CAAEC,CAAF,CAAQC,CAAR,CAAkB,CAiFnCC,QAASA,EAAa,CAAEC,CAAF,CAAOC,CAAP,CAAgBC,CAAhB,CAAsBC,CAAtB,CAA8B,CAClDF,CAAA,CAAUrB,CAAAwB,UAAA,CAAkBH,CAAlB,CACV,IAAKI,CAAA,CAAeJ,CAAf,CAAL,CACE,IAAA,CAAQK,CAAAC,KAAA,EAAR,EAAwBC,CAAA,CAAgBF,CAAAC,KAAA,EAAhB,CAAxB,CAAA,CACEE,CAAA,CAAa,EAAb,CAAiBH,CAAAC,KAAA,EAAjB,CAICG,EAAA,CAAwBT,CAAxB,CAAL,EAA0CK,CAAAC,KAAA,EAA1C,EAA0DN,CAA1D,EACEQ,CAAA,CAAa,EAAb,CAAiBR,CAAjB,CAKF,EAFAE,CAEA,CAFQQ,CAAA,CAAcV,CAAd,CAER,EAFmC,CAAC,CAACE,CAErC,GACEG,CAAAM,KAAA,CAAYX,CAAZ,CAEF,KAAIY,EAAQ,EAEZX,EAAAY,QAAA,CAAaC,CAAb,CACE,QAAQ,CAACC,CAAD,CAAQC,CAAR,CAAcC,CAAd,CAAiCC,CAAjC,CAAoDC,CAApD,CAAmE,CAMzEP,CAAA,CAAMI,CAAN,CAAA,CAAcI,CAAA,CALFH,CAKE,EAJTC,CAIS,EAHTC,CAGS,EAFT,EAES,CAN2D,CAD7E,CASItB,EAAAwB,MAAJ,EAAmBxB,CAAAwB,MAAA,CAAerB,CAAf,CAAwBY,CAAxB,CAA+BV,CAA/B,CA5B+B,CA+BpDM,QAASA,EAAW,CAAET,CAAF,CAAOC,CAAP,CAAiB,CAAA,IAC/BsB,EAAM,CADyB,CACtB7B,CAEb,IADAO,CACA,CADUrB,CAAAwB,UAAA,CAAkBH,CAAlB,CACV,CAEE,IAAMsB,CAAN,CAAYjB,CAAAX,OAAZ,CAA2B,CAA3B,CAAqC,CAArC,EAA8B4B,CAA9B,EACOjB,CAAA,CAAOiB,CAAP,CADP,EACuBtB,CADvB,CAAwCsB,CAAA,EAAxC;AAIF,GAAY,CAAZ,EAAKA,CAAL,CAAgB,CAEd,IAAM7B,CAAN,CAAUY,CAAAX,OAAV,CAAyB,CAAzB,CAA4BD,CAA5B,EAAiC6B,CAAjC,CAAsC7B,CAAA,EAAtC,CACMI,CAAA0B,IAAJ,EAAiB1B,CAAA0B,IAAA,CAAalB,CAAA,CAAOZ,CAAP,CAAb,CAGnBY,EAAAX,OAAA,CAAe4B,CAND,CATmB,CAhHF,IAC/BE,CAD+B,CACxB1C,CADwB,CACVuB,EAAQ,EADE,CACEC,EAAOV,CAG5C,KAFAS,CAAAC,KAEA,CAFamB,QAAQ,EAAG,CAAE,MAAOpB,EAAA,CAAOA,CAAAX,OAAP,CAAsB,CAAtB,CAAT,CAExB,CAAQE,CAAR,CAAA,CAAe,CACbd,CAAA,CAAQ,CAAA,CAGR,IAAMuB,CAAAC,KAAA,EAAN,EAAuBoB,CAAA,CAAiBrB,CAAAC,KAAA,EAAjB,CAAvB,CAmDEV,CASA,CATOA,CAAAiB,QAAA,CAAiBc,MAAJ,CAAW,kBAAX,CAAgCtB,CAAAC,KAAA,EAAhC,CAA+C,QAA/C,CAAyD,GAAzD,CAAb,CACL,QAAQ,CAACsB,CAAD,CAAMC,CAAN,CAAW,CACjBA,CAAA,CAAOA,CAAAhB,QAAA,CAAaiB,CAAb,CAA6B,IAA7B,CAAAjB,QAAA,CAA2CkB,CAA3C,CAAyD,IAAzD,CAEHlC,EAAAf,MAAJ,EAAmBe,CAAAf,MAAA,CAAesC,CAAA,CAAeS,CAAf,CAAf,CAEnB,OAAO,EALU,CADd,CASP,CAAArB,CAAA,CAAa,EAAb,CAAiBH,CAAAC,KAAA,EAAjB,CA5DF,KAAyD,CAGvD,GAA8B,CAA9B,GAAKV,CAAAoC,QAAA,CAAa,SAAb,CAAL,CAEER,CAEA,CAFQ5B,CAAAoC,QAAA,CAAa,IAAb,CAAmB,CAAnB,CAER,CAAc,CAAd,EAAKR,CAAL,EAAmB5B,CAAAqC,YAAA,CAAiB,QAAjB,CAAwBT,CAAxB,CAAnB,GAAsDA,CAAtD,GACM3B,CAAAqC,QAEJ,EAFqBrC,CAAAqC,QAAA,CAAiBtC,CAAAuC,UAAA,CAAgB,CAAhB,CAAmBX,CAAnB,CAAjB,CAErB,CADA5B,CACA,CADOA,CAAAuC,UAAA,CAAgBX,CAAhB,CAAwB,CAAxB,CACP,CAAA1C,CAAA,CAAQ,CAAA,CAHV,CAJF,KAUO,IAAKsD,CAAAC,KAAA,CAAoBzC,CAApB,CAAL,CAGL,IAFAmB,CAEA,CAFQnB,CAAAmB,MAAA,CAAYqB,CAAZ,CAER,CACExC,CACA;AADOA,CAAAiB,QAAA,CAAcE,CAAA,CAAM,CAAN,CAAd,CAAwB,EAAxB,CACP,CAAAjC,CAAA,CAAQ,CAAA,CAFV,CAHK,IAQA,IAAKwD,CAAAD,KAAA,CAA4BzC,CAA5B,CAAL,CAGL,IAFAmB,CAEA,CAFQnB,CAAAmB,MAAA,CAAYwB,CAAZ,CAER,CACE3C,CAEA,CAFOA,CAAAuC,UAAA,CAAgBpB,CAAA,CAAM,CAAN,CAAArB,OAAhB,CAEP,CADAqB,CAAA,CAAM,CAAN,CAAAF,QAAA,CAAkB0B,CAAlB,CAAkC/B,CAAlC,CACA,CAAA1B,CAAA,CAAQ,CAAA,CAHV,CAHK,IAUK0D,EAAAH,KAAA,CAAsBzC,CAAtB,CAAL,GACLmB,CADK,CACGnB,CAAAmB,MAAA,CAAY0B,CAAZ,CADH,IAIH7C,CAEA,CAFOA,CAAAuC,UAAA,CAAgBpB,CAAA,CAAM,CAAN,CAAArB,OAAhB,CAEP,CADAqB,CAAA,CAAM,CAAN,CAAAF,QAAA,CAAkB4B,CAAlB,CAAoC3C,CAApC,CACA,CAAAhB,CAAA,CAAQ,CAAA,CANL,CAUFA,EAAL,GACE0C,CAKA,CALQ5B,CAAAoC,QAAA,CAAa,GAAb,CAKR,CAHIH,CAGJ,CAHmB,CAAR,CAAAL,CAAA,CAAY5B,CAAZ,CAAmBA,CAAAuC,UAAA,CAAgB,CAAhB,CAAmBX,CAAnB,CAG9B,CAFA5B,CAEA,CAFe,CAAR,CAAA4B,CAAA,CAAY,EAAZ,CAAiB5B,CAAAuC,UAAA,CAAgBX,CAAhB,CAExB,CAAI3B,CAAAf,MAAJ,EAAmBe,CAAAf,MAAA,CAAesC,CAAA,CAAeS,CAAf,CAAf,CANrB,CAzCuD,CA+DzD,GAAKjC,CAAL,EAAaU,CAAb,CACE,KAAMoC,EAAA,CAAgB,UAAhB,CAC4C9C,CAD5C,CAAN,CAGFU,CAAA,CAAOV,CAvEM,CA2EfY,CAAA,EA/EmC,CA2IrCY,QAASA,EAAc,CAACuB,CAAD,CAAQ,CAC7B,GAAI,CAACA,CAAL,CAAc,MAAO,EAIrB,KAAIC,EAAQC,CAAAC,KAAA,CAAaH,CAAb,CACRI,EAAAA,CAAcH,CAAA,CAAM,CAAN,CAClB,KAAII,EAAaJ,CAAA,CAAM,CAAN,CAEjB,IADIK,CACJ,CADcL,CAAA,CAAM,CAAN,CACd,CACEM,CAAAC,UAKA,CALoBF,CAAApC,QAAA,CAAgB,IAAhB,CAAqB,MAArB,CAKpB,CAAAoC,CAAA,CAAU,aAAA,EAAiBC,EAAjB,CACRA,CAAAE,YADQ,CACgBF,CAAAG,UAE5B,OAAON,EAAP,CAAqBE,CAArB,CAA+BD,CAlBF,CA4B/BM,QAASA,EAAc,CAACX,CAAD,CAAQ,CAC7B,MAAOA,EAAA9B,QAAA,CACG,IADH;AACS,OADT,CAAAA,QAAA,CAEG0C,CAFH,CAE4B,QAAQ,CAACZ,CAAD,CAAO,CAC9C,MAAO,IAAP,CAAcA,CAAAa,WAAA,CAAiB,CAAjB,CAAd,CAAoC,GADU,CAF3C,CAAA3C,QAAA,CAKG,IALH,CAKS,MALT,CAAAA,QAAA,CAMG,IANH,CAMS,MANT,CADsB,CAoB/B7B,QAASA,EAAkB,CAACD,CAAD,CAAM0E,CAAN,CAAmB,CAC5C,IAAIC,EAAS,CAAA,CAAb,CACIC,EAAMhF,CAAAiF,KAAA,CAAa7E,CAAb,CAAkBA,CAAA4B,KAAlB,CACV,OAAO,OACEU,QAAQ,CAACtB,CAAD,CAAMa,CAAN,CAAaV,CAAb,CAAmB,CAChCH,CAAA,CAAMpB,CAAAwB,UAAA,CAAkBJ,CAAlB,CACD2D,EAAAA,CAAL,EAAehC,CAAA,CAAgB3B,CAAhB,CAAf,GACE2D,CADF,CACW3D,CADX,CAGK2D,EAAL,EAAsC,CAAA,CAAtC,GAAeG,CAAA,CAAc9D,CAAd,CAAf,GACE4D,CAAA,CAAI,GAAJ,CAcA,CAbAA,CAAA,CAAI5D,CAAJ,CAaA,CAZApB,CAAAmF,QAAA,CAAgBlD,CAAhB,CAAuB,QAAQ,CAAC+B,CAAD,CAAQoB,CAAR,CAAY,CACzC,IAAIC,EAAKrF,CAAAwB,UAAA,CAAkB4D,CAAlB,CAAT,CACIE,EAAmB,KAAnBA,GAAWlE,CAAXkE,EAAqC,KAArCA,GAA4BD,CAA5BC,EAAyD,YAAzDA,GAAgDD,CAC3B,EAAA,CAAzB,GAAIE,CAAA,CAAWF,CAAX,CAAJ,EACsB,CAAA,CADtB,GACGG,CAAA,CAASH,CAAT,CADH,EAC8B,CAAAP,CAAA,CAAad,CAAb,CAAoBsB,CAApB,CAD9B,GAEEN,CAAA,CAAI,GAAJ,CAIA,CAHAA,CAAA,CAAII,CAAJ,CAGA,CAFAJ,CAAA,CAAI,IAAJ,CAEA,CADAA,CAAA,CAAIL,CAAA,CAAeX,CAAf,CAAJ,CACA,CAAAgB,CAAA,CAAI,GAAJ,CANF,CAHyC,CAA3C,CAYA,CAAAA,CAAA,CAAIzD,CAAA,CAAQ,IAAR,CAAe,GAAnB,CAfF,CALgC,CAD7B,KAwBAqB,QAAQ,CAACxB,CAAD,CAAK,CACdA,CAAA,CAAMpB,CAAAwB,UAAA,CAAkBJ,CAAlB,CACD2D,EAAL,EAAsC,CAAA,CAAtC,GAAeG,CAAA,CAAc9D,CAAd,CAAf,GACE4D,CAAA,CAAI,IAAJ,CAEA,CADAA,CAAA,CAAI5D,CAAJ,CACA,CAAA4D,CAAA,CAAI,GAAJ,CAHF,CAKI5D,EAAJ,EAAW2D,CAAX,GACEA,CADF,CACW,CAAA,CADX,CAPc,CAxBb,OAmCE5E,QAAQ,CAACA,CAAD,CAAO,CACb4E,CAAL;AACEC,CAAA,CAAIL,CAAA,CAAexE,CAAf,CAAJ,CAFgB,CAnCjB,CAHqC,CAha9C,IAAI4D,EAAkB/D,CAAAyF,SAAA,CAAiB,WAAjB,CAAtB,CAwJI3B,EACG,4FAzJP,CA0JEF,EAAiB,2BA1JnB,CA2JEzB,EAAc,yEA3JhB,CA4JE0B,EAAmB,IA5JrB,CA6JEF,EAAyB,SA7J3B,CA8JER,EAAiB,qBA9JnB,CA+JEM,EAAiB,qBA/JnB,CAgKEL,EAAe,yBAhKjB,CAkKEwB,EAA0B,gBAlK5B,CA2KI7C,EAAetB,CAAA,CAAQ,wBAAR,CAIfiF,EAAAA,CAA8BjF,CAAA,CAAQ,gDAAR,CAC9BkF,EAAAA,CAA+BlF,CAAA,CAAQ,OAAR,CADnC,KAEIqB,EAAyB9B,CAAA4F,OAAA,CAAe,EAAf,CACeD,CADf,CAEeD,CAFf,CAF7B,CAOIjE,EAAgBzB,CAAA4F,OAAA,CAAe,EAAf,CAAmBF,CAAnB,CAAgDjF,CAAA,CAAQ,4KAAR,CAAhD,CAPpB;AAYImB,EAAiB5B,CAAA4F,OAAA,CAAe,EAAf,CAAmBD,CAAnB,CAAiDlF,CAAA,CAAQ,2JAAR,CAAjD,CAZrB,CAkBIsC,EAAkBtC,CAAA,CAAQ,cAAR,CAlBtB,CAoBIyE,EAAgBlF,CAAA4F,OAAA,CAAe,EAAf,CACe7D,CADf,CAEeN,CAFf,CAGeG,CAHf,CAIeE,CAJf,CApBpB,CA2BI0D,EAAW/E,CAAA,CAAQ,0CAAR,CA3Bf,CA4BI8E,EAAavF,CAAA4F,OAAA,CAAe,EAAf,CAAmBJ,CAAnB,CAA6B/E,CAAA,CAC1C,ySAD0C,CAA7B,CA5BjB;AA0LI8D,EAAUsB,QAAAC,cAAA,CAAuB,KAAvB,CA1Ld,CA2LI5B,EAAU,wBAsGdlE,EAAA+F,OAAA,CAAe,YAAf,CAA6B,EAA7B,CAAAC,SAAA,CAA0C,WAA1C,CA7UAC,QAA0B,EAAG,CAC3B,IAAAC,KAAA,CAAY,CAAC,eAAD,CAAkB,QAAQ,CAACC,CAAD,CAAgB,CACpD,MAAO,SAAQ,CAAClF,CAAD,CAAO,CACpB,IAAIb,EAAM,EACVY,EAAA,CAAWC,CAAX,CAAiBZ,CAAA,CAAmBD,CAAnB,CAAwB,QAAQ,CAACgG,CAAD,CAAMd,CAAN,CAAe,CAC9D,MAAO,CAAC,SAAA5B,KAAA,CAAeyC,CAAA,CAAcC,CAAd,CAAmBd,CAAnB,CAAf,CADsD,CAA/C,CAAjB,CAGA,OAAOlF,EAAAI,KAAA,CAAS,EAAT,CALa,CAD8B,CAA1C,CADe,CA6U7B,CAuGAR,EAAA+F,OAAA,CAAe,YAAf,CAAAM,OAAA,CAAoC,OAApC,CAA6C,CAAC,WAAD,CAAc,QAAQ,CAACC,CAAD,CAAY,CAAA,IACzEC,EACE,mEAFuE,CAGzEC,EAAgB,UAEpB,OAAO,SAAQ,CAACtD,CAAD,CAAOuD,CAAP,CAAe,CAoB5BC,QAASA,EAAO,CAACxD,CAAD,CAAO,CAChBA,CAAL,EAGAjC,CAAAe,KAAA,CAAU9B,CAAA,CAAagD,CAAb,CAAV,CAJqB,CAOvByD,QAASA,EAAO,CAACC,CAAD,CAAM1D,CAAN,CAAY,CAC1BjC,CAAAe,KAAA,CAAU,KAAV,CACIhC,EAAA6G,UAAA,CAAkBJ,CAAlB,CAAJ;CACExF,CAAAe,KAAA,CAAU,UAAV,CAEA,CADAf,CAAAe,KAAA,CAAUyE,CAAV,CACA,CAAAxF,CAAAe,KAAA,CAAU,IAAV,CAHF,CAKAf,EAAAe,KAAA,CAAU,QAAV,CACAf,EAAAe,KAAA,CAAU4E,CAAV,CACA3F,EAAAe,KAAA,CAAU,IAAV,CACA0E,EAAA,CAAQxD,CAAR,CACAjC,EAAAe,KAAA,CAAU,MAAV,CAX0B,CA1B5B,GAAI,CAACkB,CAAL,CAAW,MAAOA,EAMlB,KALA,IAAId,CAAJ,CACI0E,EAAM5D,CADV,CAEIjC,EAAO,EAFX,CAGI2F,CAHJ,CAII9F,CACJ,CAAQsB,CAAR,CAAgB0E,CAAA1E,MAAA,CAAUmE,CAAV,CAAhB,CAAA,CAEEK,CAMA,CANMxE,CAAA,CAAM,CAAN,CAMN,CAJIA,CAAA,CAAM,CAAN,CAIJ,EAJgBA,CAAA,CAAM,CAAN,CAIhB,GAJ0BwE,CAI1B,CAJgC,SAIhC,CAJ4CA,CAI5C,EAHA9F,CAGA,CAHIsB,CAAAS,MAGJ,CAFA6D,CAAA,CAAQI,CAAAC,OAAA,CAAW,CAAX,CAAcjG,CAAd,CAAR,CAEA,CADA6F,CAAA,CAAQC,CAAR,CAAaxE,CAAA,CAAM,CAAN,CAAAF,QAAA,CAAiBsE,CAAjB,CAAgC,EAAhC,CAAb,CACA,CAAAM,CAAA,CAAMA,CAAAtD,UAAA,CAAc1C,CAAd,CAAkBsB,CAAA,CAAM,CAAN,CAAArB,OAAlB,CAER2F,EAAA,CAAQI,CAAR,CACA,OAAOR,EAAA,CAAUrF,CAAAT,KAAA,CAAU,EAAV,CAAV,CAlBqB,CAL+C,CAAlC,CAA7C,CAzjBsC,CAArC,CAAA,CA0mBET,MA1mBF,CA0mBUA,MAAAC,QA1mBV;", -"sources":["angular-sanitize.js"], -"names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","makeMap","str","obj","items","split","i","length","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","lowercase","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","stack.last","specialElements","RegExp","all","text","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","parts","spaceRe","exec","spaceBefore","spaceAfter","content","hiddenPre","innerHTML","textContent","innerText","encodeEntities","NON_ALPHANUMERIC_REGEXP","charCodeAt","uriValidator","ignore","out","bind","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","document","createElement","module","provider","$SanitizeProvider","$get","$$sanitizeUri","uri","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","target","addText","addLink","url","isDefined","raw","substr"] -} diff --git a/dist/bower_components/angular-sanitize/bower.json b/dist/bower_components/angular-sanitize/bower.json deleted file mode 100644 index 1160f22ff..000000000 --- a/dist/bower_components/angular-sanitize/bower.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "angular-sanitize", - "version": "1.2.16", - "main": "./angular-sanitize.js", - "dependencies": { - "angular": "1.2.16" - } -} diff --git a/dist/bower_components/angular-scenario/.bower.json b/dist/bower_components/angular-scenario/.bower.json deleted file mode 100644 index e86e02f7f..000000000 --- a/dist/bower_components/angular-scenario/.bower.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "angular-scenario", - "version": "1.2.8", - "main": "./angular-scenario.js", - "dependencies": { - "angular": "1.2.8" - }, - "homepage": "https://github.com/angular/bower-angular-scenario", - "_release": "1.2.8", - "_resolution": { - "type": "version", - "tag": "v1.2.8", - "commit": "ad9ea87eca812bb19e8631ffa9573aef6b14c65f" - }, - "_source": "git://github.com/angular/bower-angular-scenario.git", - "_target": "1.2.8", - "_originalSource": "angular-scenario" -} \ No newline at end of file diff --git a/dist/bower_components/angular-scenario/README.md b/dist/bower_components/angular-scenario/README.md deleted file mode 100644 index 7f80a8c55..000000000 --- a/dist/bower_components/angular-scenario/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# bower-angular-scenario - -This repo is for distribution on `bower`. The source for this module is in the -[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngScenario). -Please file issues and pull requests against that repo. - -## Install - -Install with `bower`: - -```shell -bower install angular-scenario -``` - -## Documentation - -Documentation is available on the -[AngularJS docs site](http://docs.angularjs.org/). - -## License - -The MIT License - -Copyright (c) 2010-2012 Google, Inc. http://angularjs.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/dist/bower_components/angular-scenario/angular-scenario.js b/dist/bower_components/angular-scenario/angular-scenario.js deleted file mode 100644 index a6b4ac25b..000000000 --- a/dist/bower_components/angular-scenario/angular-scenario.js +++ /dev/null @@ -1,32560 +0,0 @@ -/*! - * jQuery JavaScript Library v1.10.2 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2013-07-03T13:48Z - */ -(function( window, undefined ) {'use strict'; - -// Can't do this because several apps including ASP.NET trace -// the stack via arguments.caller.callee and Firefox dies if -// you try to trace through "use strict" call chains. (#13335) -// Support: Firefox 18+ -// - -var - // The deferred used on DOM ready - readyList, - - // A central reference to the root jQuery(document) - rootjQuery, - - // Support: IE<10 - // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` - core_strundefined = typeof undefined, - - // Use the correct document accordingly with window argument (sandbox) - location = window.location, - document = window.document, - docElem = document.documentElement, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // [[Class]] -> type pairs - class2type = {}, - - // List of deleted data cache ids, so we can reuse them - core_deletedIds = [], - - core_version = "1.10.2", - - // Save a reference to some core methods - core_concat = core_deletedIds.concat, - core_push = core_deletedIds.push, - core_slice = core_deletedIds.slice, - core_indexOf = core_deletedIds.indexOf, - core_toString = class2type.toString, - core_hasOwn = class2type.hasOwnProperty, - core_trim = core_version.trim, - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Used for matching numbers - core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, - - // Used for splitting on whitespace - core_rnotwhite = /\S+/g, - - // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, - rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }, - - // The ready event handler - completed = function( event ) { - - // readyState === "complete" is good enough for us to call the dom ready in oldIE - if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { - detach(); - jQuery.ready(); - } - }, - // Clean-up method for dom ready events - detach = function() { - if ( document.addEventListener ) { - document.removeEventListener( "DOMContentLoaded", completed, false ); - window.removeEventListener( "load", completed, false ); - - } else { - document.detachEvent( "onreadystatechange", completed ); - window.detachEvent( "onload", completed ); - } - }; - -jQuery.fn = jQuery.prototype = { - // The current version of jQuery being used - jquery: core_version, - - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - - // scripts is true for back-compat - jQuery.merge( this, jQuery.parseHTML( - match[1], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return core_slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - ret.context = this.context; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Add the callback - jQuery.ready.promise().done( fn ); - - return this; - }, - - slice: function() { - return this.pushStack( core_slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: core_push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var src, copyIsArray, copy, name, options, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - // Unique for each copy of jQuery on the page - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), - - noConflict: function( deep ) { - if ( window.$ === jQuery ) { - window.$ = _$; - } - - if ( deep && window.jQuery === jQuery ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger("ready").off("ready"); - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - isWindow: function( obj ) { - /* jshint eqeqeq: false */ - return obj != null && obj == obj.window; - }, - - isNumeric: function( obj ) { - return !isNaN( parseFloat(obj) ) && isFinite( obj ); - }, - - type: function( obj ) { - if ( obj == null ) { - return String( obj ); - } - return typeof obj === "object" || typeof obj === "function" ? - class2type[ core_toString.call(obj) ] || "object" : - typeof obj; - }, - - isPlainObject: function( obj ) { - var key; - - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - try { - // Not own constructor property must be Object - if ( obj.constructor && - !core_hasOwn.call(obj, "constructor") && - !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Support: IE<9 - // Handle iteration over inherited properties before own properties. - if ( jQuery.support.ownLast ) { - for ( key in obj ) { - return core_hasOwn.call( obj, key ); - } - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - for ( key in obj ) {} - - return key === undefined || core_hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw new Error( msg ); - }, - - // data: string of html - // context (optional): If specified, the fragment will be created in this context, defaults to document - // keepScripts (optional): If true, will include scripts passed in the html string - parseHTML: function( data, context, keepScripts ) { - if ( !data || typeof data !== "string" ) { - return null; - } - if ( typeof context === "boolean" ) { - keepScripts = context; - context = false; - } - context = context || document; - - var parsed = rsingleTag.exec( data ), - scripts = !keepScripts && []; - - // Single tag - if ( parsed ) { - return [ context.createElement( parsed[1] ) ]; - } - - parsed = jQuery.buildFragment( [ data ], context, scripts ); - if ( scripts ) { - jQuery( scripts ).remove(); - } - return jQuery.merge( [], parsed.childNodes ); - }, - - parseJSON: function( data ) { - // Attempt to parse using the native JSON parser first - if ( window.JSON && window.JSON.parse ) { - return window.JSON.parse( data ); - } - - if ( data === null ) { - return data; - } - - if ( typeof data === "string" ) { - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - if ( data ) { - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { - - return ( new Function( "return " + data ) )(); - } - } - } - - jQuery.error( "Invalid JSON: " + data ); - }, - - // Cross-browser xml parsing - parseXML: function( data ) { - var xml, tmp; - if ( !data || typeof data !== "string" ) { - return null; - } - try { - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - } catch( e ) { - xml = undefined; - } - if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; - }, - - noop: function() {}, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function( data ) { - if ( data && jQuery.trim( data ) ) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); - } )( data ); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - // args is for internal usage only - each: function( obj, callback, args ) { - var value, - i = 0, - length = obj.length, - isArray = isArraylike( obj ); - - if ( args ) { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } - } - - return obj; - }, - - // Use native String.trim function wherever possible - trim: core_trim && !core_trim.call("\uFEFF\xA0") ? - function( text ) { - return text == null ? - "" : - core_trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArraylike( Object(arr) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - core_push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - var len; - - if ( arr ) { - if ( core_indexOf ) { - return core_indexOf.call( arr, elem, i ); - } - - len = arr.length; - i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; - - for ( ; i < len; i++ ) { - // Skip accessing in sparse arrays - if ( i in arr && arr[ i ] === elem ) { - return i; - } - } - } - - return -1; - }, - - merge: function( first, second ) { - var l = second.length, - i = first.length, - j = 0; - - if ( typeof l === "number" ) { - for ( ; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var retVal, - ret = [], - i = 0, - length = elems.length; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, - i = 0, - length = elems.length, - isArray = isArraylike( elems ), - ret = []; - - // Go through the array, translating each of the items to their - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - } - - // Flatten any nested arrays - return core_concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var args, proxy, tmp; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = core_slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - // Multifunctional method to get and set values of a collection - // The value/s can optionally be executed if it's a function - access: function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - length = elems.length, - bulk = key == null; - - // Sets many values - if ( jQuery.type( key ) === "object" ) { - chainable = true; - for ( i in key ) { - jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !jQuery.isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < length; i++ ) { - fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); - } - } - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - length ? fn( elems[0], key ) : emptyGet; - }, - - now: function() { - return ( new Date() ).getTime(); - }, - - // A method for quickly swapping in/out CSS properties to get correct calculations. - // Note: this method belongs to the css module but it's needed here for the support module. - // If support gets modularized, this method should be moved back to the css module. - swap: function( elem, options, callback, args ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; - } -}); - -jQuery.ready.promise = function( obj ) { - if ( !readyList ) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // we once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready ); - - // Standards-based browsers support DOMContentLoaded - } else if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed, false ); - - // If IE event model is used - } else { - // Ensure firing before onload, maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", completed ); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", completed ); - - // If IE and not a frame - // continually check to see if the document is ready - var top = false; - - try { - top = window.frameElement == null && document.documentElement; - } catch(e) {} - - if ( top && top.doScroll ) { - (function doScrollCheck() { - if ( !jQuery.isReady ) { - - try { - // Use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - top.doScroll("left"); - } catch(e) { - return setTimeout( doScrollCheck, 50 ); - } - - // detach all dom ready events - detach(); - - // and execute any waiting functions - jQuery.ready(); - } - })(); - } - } - } - return readyList.promise( obj ); -}; - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -function isArraylike( obj ) { - var length = obj.length, - type = jQuery.type( obj ); - - if ( jQuery.isWindow( obj ) ) { - return false; - } - - if ( obj.nodeType === 1 && length ) { - return true; - } - - return type === "array" || type !== "function" && - ( length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj ); -} - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); -/*! - * Sizzle CSS Selector Engine v1.10.2 - * http://sizzlejs.com/ - * - * Copyright 2013 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2013-07-03 - */ -(function( window, undefined ) { - -var i, - support, - cachedruns, - Expr, - getText, - isXML, - compile, - outermostContext, - sortInput, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + -(new Date()), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - hasDuplicate = false, - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - return 0; - }, - - // General-purpose constants - strundefined = typeof undefined, - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf if we can't use a native one - indexOf = arr.indexOf || function( elem ) { - var i = 0, - len = this.length; - for ( ; i < len; i++ ) { - if ( this[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + - "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", - - // Prefer arguments quoted, - // then not containing pseudos/brackets, - // then attribute selectors/non-parenthetical expressions, - // then anything else - // These preferences are here to reduce the number of selectors - // needing tokenize in the PSEUDO preFilter - pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rsibling = new RegExp( whitespace + "*[+~]" ), - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - // BMP codepoint - high < 0 ? - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }; - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var match, elem, m, nodeType, - // QSA vars - i, groups, old, nid, newContext, newSelector; - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - - context = context || document; - results = results || []; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { - return []; - } - - if ( documentIsHTML && !seed ) { - - // Shortcuts - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // QSA path - if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - nid = old = expando; - newContext = context; - newSelector = nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + toSelector( groups[i] ); - } - newContext = rsibling.test( selector ) && context.parentNode || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {Function(string, Object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key += " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created div and expects a boolean result - */ -function assert( fn ) { - var div = document.createElement("div"); - - try { - return !!fn( div ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( div.parentNode ) { - div.parentNode.removeChild( div ); - } - // release memory in IE - div = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = attrs.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - ( ~b.sourceIndex || MAX_NEGATIVE ) - - ( ~a.sourceIndex || MAX_NEGATIVE ); - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Detect xml - * @param {Element|Object} elem An element or a document - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var doc = node ? node.ownerDocument || node : preferredDoc, - parent = doc.defaultView; - - // If no document and documentElement is available, return - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Set our document - document = doc; - docElem = doc.documentElement; - - // Support tests - documentIsHTML = !isXML( doc ); - - // Support: IE>8 - // If iframe document is assigned to "document" variable and if iframe has been reloaded, - // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 - // IE6-8 do not support the defaultView property so parent will be undefined - if ( parent && parent.attachEvent && parent !== parent.top ) { - parent.attachEvent( "onbeforeunload", function() { - setDocument(); - }); - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) - support.attributes = assert(function( div ) { - div.className = "i"; - return !div.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( div ) { - div.appendChild( doc.createComment("") ); - return !div.getElementsByTagName("*").length; - }); - - // Check if getElementsByClassName can be trusted - support.getElementsByClassName = assert(function( div ) { - div.innerHTML = "
      "; - - // Support: Safari<4 - // Catch class over-caching - div.firstChild.className = "i"; - // Support: Opera<10 - // Catch gEBCN failure to find non-leading classes - return div.getElementsByClassName("i").length === 2; - }); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( div ) { - docElem.appendChild( div ).id = expando; - return !doc.getElementsByName || !doc.getElementsByName( expando ).length; - }); - - // ID find and filter - if ( support.getById ) { - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== strundefined && documentIsHTML ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }; - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var elem, - tmp = [], - i = 0, - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = ""; - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - - // Support: Opera 10-12/IE8 - // ^= $= *= and empty values - // Should not select anything - // Support: Windows 8 Native Apps - // The type attribute is restricted during .innerHTML assignment - var input = doc.createElement("input"); - input.setAttribute( "type", "hidden" ); - div.appendChild( input ).setAttribute( "t", "" ); - - if ( div.querySelectorAll("[t^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( div, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - - // Element contains another - // Purposefully does not implement inclusive descendent - // As in, an element does not contain itself - contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = docElem.compareDocumentPosition ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); - - if ( compare ) { - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === doc || contains(preferredDoc, a) ) { - return -1; - } - if ( b === doc || contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } - - // Not directly comparable, sort on existence of method - return a.compareDocumentPosition ? -1 : 1; - } : - function( a, b ) { - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Parentless nodes are either documents or disconnected - } else if ( !aup || !bup ) { - return a === doc ? -1 : - b === doc ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return doc; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, document, null, [elem] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val === undefined ? - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null : - val; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - for ( ; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (see #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[5] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] && match[4] !== undefined ) { - match[2] = match[4]; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, outerCache, node, diff, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - // Seek `elem` from a previously-cached index - outerCache = parent[ expando ] || (parent[ expando ] = {}); - cache = outerCache[ type ] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - outerCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - // Use previously-cached element index if available - } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { - diff = cache[1]; - - // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) - } else { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { - // Cache the index of each encountered element - if ( useCache ) { - (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), - // not comment, processing instructions, or others - // Thanks to Diego Perini for the nodeName shortcut - // Greater than "@" means alpha characters (specifically not starting with "#" or "?") - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -function tokenize( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( tokens = [] ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -} - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var data, cache, outerCache, - dirkey = dirruns + " " + doneName; - - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { - if ( (data = cache[1]) === true || data === cachedruns ) { - return data === true; - } - } else { - cache = outerCache[ dir ] = [ dirkey ]; - cache[1] = matcher( elem, context, xml ) || cachedruns; - if ( cache[1] === true ) { - return true; - } - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - // A counter to specify which element is currently being matched - var matcherCachedRuns = 0, - bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, expandContext ) { - var elem, j, matcher, - setMatched = [], - matchedCount = 0, - i = "0", - unmatched = seed && [], - outermost = expandContext != null, - contextBackup = outermostContext, - // We must always have either seed elements or context - elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); - - if ( outermost ) { - outermostContext = context !== document && context; - cachedruns = matcherCachedRuns; - } - - // Add elements passing elementMatchers directly to results - // Keep `i` a string if there are no elements so `matchedCount` will be "00" below - for ( ; (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - cachedruns = ++matcherCachedRuns; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !group ) { - group = tokenize( selector ); - } - i = group.length; - while ( i-- ) { - cached = matcherFromTokens( group[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - } - return cached; -}; - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} - -function select( selector, context, results, seed ) { - var i, tokens, token, type, find, - match = tokenize( selector ); - - if ( !seed ) { - // Try to minimize operations if there is only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - } - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && context.parentNode || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - } - - // Compile and execute a filtering function - // Provide `match` to avoid retokenization if we modified the selector above - compile( selector, match )( - seed, - context, - !documentIsHTML, - results, - rsibling.test( selector ) - ); - return results; -} - -// One-time assignments - -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - -// Support: Chrome<14 -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( div1 ) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition( document.createElement("div") ) & 1; -}); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( div ) { - div.innerHTML = ""; - return div.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( div ) { - div.innerHTML = ""; - div.firstChild.setAttribute( "value", "" ); - return div.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( div ) { - return div.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - elem[ name ] === true ? name.toLowerCase() : null; - } - }); -} - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})( window ); -// String to Object options format cache -var optionsCache = {}; - -// Convert String-formatted options into Object-formatted ones and store in cache -function createOptions( options ) { - var object = optionsCache[ options ] = {}; - jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { - object[ flag ] = true; - }); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - ( optionsCache[ options ] || createOptions( options ) ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // First callback to fire (used internally by add and fireWith) - firingStart, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function( data ) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { - memory = false; // To prevent further calls using add - break; - } - } - firing = false; - if ( list ) { - if ( stack ) { - if ( stack.length ) { - fire( stack.shift() ); - } - } else if ( memory ) { - list = []; - } else { - self.disable(); - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - // First, we save the current length - var start = list.length; - (function add( args ) { - jQuery.each( args, function( _, arg ) { - var type = jQuery.type( arg ); - if ( type === "function" ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && type !== "string" ) { - // Inspect recursively - add( arg ); - } - }); - })( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if ( memory ) { - firingStart = start; - fire( memory ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - jQuery.each( arguments, function( _, arg ) { - var index; - while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - // Handle firing indexes - if ( firing ) { - if ( index <= firingLength ) { - firingLength--; - } - if ( index <= firingIndex ) { - firingIndex--; - } - } - } - }); - } - return this; - }, - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); - }, - // Remove all callbacks from the list - empty: function() { - list = []; - firingLength = 0; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( list && ( !fired || stack ) ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - if ( firing ) { - stack.push( args ); - } else { - fire( args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; -jQuery.extend({ - - Deferred: function( func ) { - var tuples = [ - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], - [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], - [ "notify", "progress", jQuery.Callbacks("memory") ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred(function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var action = tuple[ 0 ], - fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ](function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); - } - }); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; - - // promise[ done | fail | progress ] = list.add - promise[ tuple[1] ] = list.add; - - // Handle state - if ( stateString ) { - list.add(function() { - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } - - // deferred[ resolve | reject | notify ] - deferred[ tuple[0] ] = function() { - deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); - return this; - }; - deferred[ tuple[0] + "With" ] = list.fireWith; - }); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = core_slice.call( arguments ), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; - if( values === progressValues ) { - deferred.notifyWith( contexts, values ); - } else if ( !( --remaining ) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ) - .progress( updateFunc( i, progressContexts, progressValues ) ); - } else { - --remaining; - } - } - } - - // if we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); - } - - return deferred.promise(); - } -}); -jQuery.support = (function( support ) { - - var all, a, input, select, fragment, opt, eventName, isSupported, i, - div = document.createElement("div"); - - // Setup - div.setAttribute( "className", "t" ); - div.innerHTML = "
      a"; - - // Finish early in limited (non-browser) environments - all = div.getElementsByTagName("*") || []; - a = div.getElementsByTagName("a")[ 0 ]; - if ( !a || !a.style || !all.length ) { - return support; - } - - // First batch of tests - select = document.createElement("select"); - opt = select.appendChild( document.createElement("option") ); - input = div.getElementsByTagName("input")[ 0 ]; - - a.style.cssText = "top:1px;float:left;opacity:.5"; - - // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) - support.getSetAttribute = div.className !== "t"; - - // IE strips leading whitespace when .innerHTML is used - support.leadingWhitespace = div.firstChild.nodeType === 3; - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - support.tbody = !div.getElementsByTagName("tbody").length; - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - support.htmlSerialize = !!div.getElementsByTagName("link").length; - - // Get the style information from getAttribute - // (IE uses .cssText instead) - support.style = /top/.test( a.getAttribute("style") ); - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - support.hrefNormalized = a.getAttribute("href") === "/a"; - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - support.opacity = /^0.5/.test( a.style.opacity ); - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - support.cssFloat = !!a.style.cssFloat; - - // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) - support.checkOn = !!input.value; - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - support.optSelected = opt.selected; - - // Tests for enctype support on a form (#6743) - support.enctype = !!document.createElement("form").enctype; - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; - - // Will be defined later - support.inlineBlockNeedsLayout = false; - support.shrinkWrapBlocks = false; - support.pixelPosition = false; - support.deleteExpando = true; - support.noCloneEvent = true; - support.reliableMarginRight = true; - support.boxSizingReliable = true; - - // Make sure checked status is properly cloned - input.checked = true; - support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Support: IE<9 - try { - delete div.test; - } catch( e ) { - support.deleteExpando = false; - } - - // Check if we can trust getAttribute("value") - input = document.createElement("input"); - input.setAttribute( "value", "" ); - support.input = input.getAttribute( "value" ) === ""; - - // Check if an input maintains its value after becoming a radio - input.value = "t"; - input.setAttribute( "type", "radio" ); - support.radioValue = input.value === "t"; - - // #11217 - WebKit loses check when the name is after the checked attribute - input.setAttribute( "checked", "t" ); - input.setAttribute( "name", "t" ); - - fragment = document.createDocumentFragment(); - fragment.appendChild( input ); - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - support.appendChecked = input.checked; - - // WebKit doesn't clone checked state correctly in fragments - support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE<9 - // Opera does not clone events (and typeof div.attachEvent === undefined). - // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() - if ( div.attachEvent ) { - div.attachEvent( "onclick", function() { - support.noCloneEvent = false; - }); - - div.cloneNode( true ).click(); - } - - // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) - // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) - for ( i in { submit: true, change: true, focusin: true }) { - div.setAttribute( eventName = "on" + i, "t" ); - - support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; - } - - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - // Support: IE<9 - // Iteration over object's inherited properties before its own. - for ( i in jQuery( support ) ) { - break; - } - support.ownLast = i !== "0"; - - // Run tests that need a body at doc ready - jQuery(function() { - var container, marginDiv, tds, - divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", - body = document.getElementsByTagName("body")[0]; - - if ( !body ) { - // Return for frameset docs that don't have a body - return; - } - - container = document.createElement("div"); - container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; - - body.appendChild( container ).appendChild( div ); - - // Support: IE8 - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - div.innerHTML = "
      t
      "; - tds = div.getElementsByTagName("td"); - tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; - isSupported = ( tds[ 0 ].offsetHeight === 0 ); - - tds[ 0 ].style.display = ""; - tds[ 1 ].style.display = "none"; - - // Support: IE8 - // Check if empty table cells still have offsetWidth/Height - support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); - - // Check box-sizing and margin behavior. - div.innerHTML = ""; - div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; - - // Workaround failing boxSizing test due to offsetWidth returning wrong value - // with some non-1 values of body zoom, ticket #13543 - jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { - support.boxSizing = div.offsetWidth === 4; - }); - - // Use window.getComputedStyle because jsdom on node.js will break without it. - if ( window.getComputedStyle ) { - support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; - support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; - - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. (#3333) - // Fails in WebKit before Feb 2011 nightlies - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - marginDiv = div.appendChild( document.createElement("div") ); - marginDiv.style.cssText = div.style.cssText = divReset; - marginDiv.style.marginRight = marginDiv.style.width = "0"; - div.style.width = "1px"; - - support.reliableMarginRight = - !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); - } - - if ( typeof div.style.zoom !== core_strundefined ) { - // Support: IE<8 - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - div.innerHTML = ""; - div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; - support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); - - // Support: IE6 - // Check if elements with layout shrink-wrap their children - div.style.display = "block"; - div.innerHTML = "
      "; - div.firstChild.style.width = "5px"; - support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); - - if ( support.inlineBlockNeedsLayout ) { - // Prevent IE 6 from affecting layout for positioned elements #11048 - // Prevent IE from shrinking the body in IE 7 mode #12869 - // Support: IE<8 - body.style.zoom = 1; - } - } - - body.removeChild( container ); - - // Null elements to avoid leaks in IE - container = div = tds = marginDiv = null; - }); - - // Null elements to avoid leaks in IE - all = select = fragment = opt = a = input = null; - - return support; -})({}); - -var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, - rmultiDash = /([A-Z])/g; - -function internalData( elem, name, data, pvt /* Internal Use Only */ ){ - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var ret, thisCache, - internalKey = jQuery.expando, - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; - } else { - id = internalKey; - } - } - - if ( !cache[ id ] ) { - // Avoid exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ] = jQuery.extend( cache[ id ], name ); - } else { - cache[ id ].data = jQuery.extend( cache[ id ].data, name ); - } - } - - thisCache = cache[ id ]; - - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if ( !pvt ) { - if ( !thisCache.data ) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } - - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( typeof name === "string" ) { - - // First Try to find as-is property data - ret = thisCache[ name ]; - - // Test for null|undefined property data - if ( ret == null ) { - - // Try to find the camelCased property - ret = thisCache[ jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; - } - - return ret; -} - -function internalRemoveData( elem, name, pvt ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, i, - isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - - thisCache = pvt ? cache[ id ] : cache[ id ].data; - - if ( thisCache ) { - - // Support array or space separated string names for data keys - if ( !jQuery.isArray( name ) ) { - - // try the string as a key before any manipulation - if ( name in thisCache ) { - name = [ name ]; - } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase( name ); - if ( name in thisCache ) { - name = [ name ]; - } else { - name = name.split(" "); - } - } - } else { - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = name.concat( jQuery.map( name, jQuery.camelCase ) ); - } - - i = name.length; - while ( i-- ) { - delete thisCache[ name[i] ]; - } - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( !pvt ) { - delete cache[ id ].data; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject( cache[ id ] ) ) { - return; - } - } - - // Destroy the cache - if ( isNode ) { - jQuery.cleanData( [ elem ], true ); - - // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) - /* jshint eqeqeq: false */ - } else if ( jQuery.support.deleteExpando || cache != cache.window ) { - /* jshint eqeqeq: true */ - delete cache[ id ]; - - // When all else fails, null - } else { - cache[ id ] = null; - } -} - -jQuery.extend({ - cache: {}, - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "applet": true, - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data ) { - return internalData( elem, name, data ); - }, - - removeData: function( elem, name ) { - return internalRemoveData( elem, name ); - }, - - // For internal use only. - _data: function( elem, name, data ) { - return internalData( elem, name, data, true ); - }, - - _removeData: function( elem, name ) { - return internalRemoveData( elem, name, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - // Do not set data on non-element because it will not be cleared (#8335). - if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { - return false; - } - - var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; - - // nodes accept data unless otherwise specified; rejection can be conditional - return !noData || noData !== true && elem.getAttribute("classid") === noData; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var attrs, name, - data = null, - i = 0, - elem = this[0]; - - // Special expections of .data basically thwart jQuery.access, - // so implement the relevant behavior ourselves - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = jQuery.data( elem ); - - if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { - attrs = elem.attributes; - for ( ; i < attrs.length; i++ ) { - name = attrs[i].name; - - if ( name.indexOf("data-") === 0 ) { - name = jQuery.camelCase( name.slice(5) ); - - dataAttr( elem, name, data[ name ] ); - } - } - jQuery._data( elem, "parsedAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - return arguments.length > 1 ? - - // Sets one value - this.each(function() { - jQuery.data( this, key, value ); - }) : - - // Gets one value - // Try to fetch any internally stored data first - elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - - var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// checks a cache object for emptiness -function isEmptyDataObject( obj ) { - var name; - for ( name in obj ) { - - // if the public data object is empty, the private is still empty - if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { - continue; - } - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} -jQuery.extend({ - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray(data) ) { - queue = jQuery._data( elem, type, jQuery.makeArray(data) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // not intended for public consumption - generates a queueHooks object, or returns the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return jQuery._data( elem, key ) || jQuery._data( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { - jQuery._removeData( elem, type + "queue" ); - jQuery._removeData( elem, key ); - }) - }); - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); - } - - return data === undefined ? - this : - this.each(function() { - var queue = jQuery.queue( this, type, data ); - - // ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = setTimeout( next, time ); - hooks.stop = function() { - clearTimeout( timeout ); - }; - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while( i-- ) { - tmp = jQuery._data( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -}); -var nodeHook, boolHook, - rclass = /[\t\r\n\f]/g, - rreturn = /\r/g, - rfocusable = /^(?:input|select|textarea|button|object)$/i, - rclickable = /^(?:a|area)$/i, - ruseDefault = /^(?:checked|selected)$/i, - getSetAttribute = jQuery.support.getSetAttribute, - getSetInput = jQuery.support.input; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - }, - - prop: function( name, value ) { - return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - name = jQuery.propFix[ name ] || name; - return this.each(function() { - // try/catch handles cases where IE balks (such as removing a property on window) - try { - this[ name ] = undefined; - delete this[ name ]; - } catch( e ) {} - }); - }, - - addClass: function( value ) { - var classes, elem, cur, clazz, j, - i = 0, - len = this.length, - proceed = typeof value === "string" && value; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).addClass( value.call( this, j, this.className ) ); - }); - } - - if ( proceed ) { - // The disjunction here is for better compressibility (see removeClass) - classes = ( value || "" ).match( core_rnotwhite ) || []; - - for ( ; i < len; i++ ) { - elem = this[ i ]; - cur = elem.nodeType === 1 && ( elem.className ? - ( " " + elem.className + " " ).replace( rclass, " " ) : - " " - ); - - if ( cur ) { - j = 0; - while ( (clazz = classes[j++]) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - elem.className = jQuery.trim( cur ); - - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, clazz, j, - i = 0, - len = this.length, - proceed = arguments.length === 0 || typeof value === "string" && value; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).removeClass( value.call( this, j, this.className ) ); - }); - } - if ( proceed ) { - classes = ( value || "" ).match( core_rnotwhite ) || []; - - for ( ; i < len; i++ ) { - elem = this[ i ]; - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( elem.className ? - ( " " + elem.className + " " ).replace( rclass, " " ) : - "" - ); - - if ( cur ) { - j = 0; - while ( (clazz = classes[j++]) ) { - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - elem.className = value ? jQuery.trim( cur ) : ""; - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value; - - if ( typeof stateVal === "boolean" && type === "string" ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( jQuery.isFunction( value ) ) { - return this.each(function( i ) { - jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - classNames = value.match( core_rnotwhite ) || []; - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space separated list - if ( self.hasClass( className ) ) { - self.removeClass( className ); - } else { - self.addClass( className ); - } - } - - // Toggle whole class name - } else if ( type === core_strundefined || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // If the element has a class name or if we're passed "false", - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - var ret, hooks, isFunction, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, jQuery( this ).val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray( val ) ) { - val = jQuery.map(val, function ( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - // Use proper attribute retrieval(#6932, #12072) - var val = jQuery.find.attr( elem, "value" ); - return val != null ? - val : - elem.text; - } - }, - select: { - get: function( elem ) { - var value, option, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one" || index < 0, - values = one ? null : [], - max = one ? index + 1 : options.length, - i = index < 0 ? - max : - one ? index : 0; - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // oldIE doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && - // Don't return options that are disabled or in a disabled optgroup - ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && - ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - }, - - set: function( elem, value ) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray( value ), - i = options.length; - - while ( i-- ) { - option = options[ i ]; - if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { - optionSet = true; - } - } - - // force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - }, - - attr: function( elem, name, value ) { - var hooks, ret, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === core_strundefined ) { - return jQuery.prop( elem, name, value ); - } - - // All attributes are lowercase - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - name = name.toLowerCase(); - hooks = jQuery.attrHooks[ name ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - - } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, value + "" ); - return value; - } - - } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, value ) { - var name, propName, - i = 0, - attrNames = value && value.match( core_rnotwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( (name = attrNames[i++]) ) { - propName = jQuery.propFix[ name ] || name; - - // Boolean attributes get special treatment (#10870) - if ( jQuery.expr.match.bool.test( name ) ) { - // Set corresponding property to false - if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { - elem[ propName ] = false; - // Support: IE<9 - // Also clear defaultChecked/defaultSelected (if appropriate) - } else { - elem[ jQuery.camelCase( "default-" + name ) ] = - elem[ propName ] = false; - } - - // See #9699 for explanation of this approach (setting first, then removal) - } else { - jQuery.attr( elem, name, "" ); - } - - elem.removeAttribute( getSetAttribute ? name : propName ); - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to default in case type is set after value during creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - }, - - propFix: { - "for": "htmlFor", - "class": "className" - }, - - prop: function( elem, name, value ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? - ret : - ( elem[ name ] = value ); - - } else { - return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? - ret : - elem[ name ]; - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - // Use proper attribute retrieval(#12072) - var tabindex = jQuery.find.attr( elem, "tabindex" ); - - return tabindex ? - parseInt( tabindex, 10 ) : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - -1; - } - } - } -}); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { - // IE<8 needs the *property* name - elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); - - // Use defaultChecked and defaultSelected for oldIE - } else { - elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; - } - - return name; - } -}; -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { - var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; - - jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? - function( elem, name, isXML ) { - var fn = jQuery.expr.attrHandle[ name ], - ret = isXML ? - undefined : - /* jshint eqeqeq: false */ - (jQuery.expr.attrHandle[ name ] = undefined) != - getter( elem, name, isXML ) ? - - name.toLowerCase() : - null; - jQuery.expr.attrHandle[ name ] = fn; - return ret; - } : - function( elem, name, isXML ) { - return isXML ? - undefined : - elem[ jQuery.camelCase( "default-" + name ) ] ? - name.toLowerCase() : - null; - }; -}); - -// fix oldIE attroperties -if ( !getSetInput || !getSetAttribute ) { - jQuery.attrHooks.value = { - set: function( elem, value, name ) { - if ( jQuery.nodeName( elem, "input" ) ) { - // Does not return so that setAttribute is also used - elem.defaultValue = value; - } else { - // Use nodeHook if defined (#1954); otherwise setAttribute is fine - return nodeHook && nodeHook.set( elem, value, name ); - } - } - }; -} - -// IE6/7 do not support getting/setting some attributes with get/setAttribute -if ( !getSetAttribute ) { - - // Use this for any attribute in IE6/7 - // This fixes almost every IE6/7 issue - nodeHook = { - set: function( elem, value, name ) { - // Set the existing or create a new attribute node - var ret = elem.getAttributeNode( name ); - if ( !ret ) { - elem.setAttributeNode( - (ret = elem.ownerDocument.createAttribute( name )) - ); - } - - ret.value = value += ""; - - // Break association with cloned elements by also using setAttribute (#9646) - return name === "value" || value === elem.getAttribute( name ) ? - value : - undefined; - } - }; - jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = - // Some attributes are constructed with empty-string values when not defined - function( elem, name, isXML ) { - var ret; - return isXML ? - undefined : - (ret = elem.getAttributeNode( name )) && ret.value !== "" ? - ret.value : - null; - }; - jQuery.valHooks.button = { - get: function( elem, name ) { - var ret = elem.getAttributeNode( name ); - return ret && ret.specified ? - ret.value : - undefined; - }, - set: nodeHook.set - }; - - // Set contenteditable to false on removals(#10429) - // Setting to empty string throws an error as an invalid value - jQuery.attrHooks.contenteditable = { - set: function( elem, value, name ) { - nodeHook.set( elem, value === "" ? false : value, name ); - } - }; - - // Set width and height to auto instead of 0 on empty string( Bug #8150 ) - // This is for removals - jQuery.each([ "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = { - set: function( elem, value ) { - if ( value === "" ) { - elem.setAttribute( name, "auto" ); - return value; - } - } - }; - }); -} - - -// Some attributes require a special call on IE -// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !jQuery.support.hrefNormalized ) { - // href/src property should get the full normalized URL (#10299/#12915) - jQuery.each([ "href", "src" ], function( i, name ) { - jQuery.propHooks[ name ] = { - get: function( elem ) { - return elem.getAttribute( name, 4 ); - } - }; - }); -} - -if ( !jQuery.support.style ) { - jQuery.attrHooks.style = { - get: function( elem ) { - // Return undefined in the case of empty string - // Note: IE uppercases css property names, but if we were to .toLowerCase() - // .cssText, that would destroy case senstitivity in URL's, like in "background" - return elem.style.cssText || undefined; - }, - set: function( elem, value ) { - return ( elem.style.cssText = value + "" ); - } - }; -} - -// Safari mis-reports the default selected property of an option -// Accessing the parent's selectedIndex property fixes it -if ( !jQuery.support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - var parent = elem.parentNode; - - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - return null; - } - }; -} - -jQuery.each([ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -}); - -// IE6/7 call enctype encoding -if ( !jQuery.support.enctype ) { - jQuery.propFix.enctype = "encoding"; -} - -// Radios and checkboxes getter/setter -jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( jQuery.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); - } - } - }; - if ( !jQuery.support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - // Support: Webkit - // "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - }; - } -}); -var rformElems = /^(?:input|select|textarea)$/i, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - var tmp, events, t, handleObjIn, - special, eventHandle, handleObj, - handlers, type, namespaces, origType, - elemData = jQuery._data( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !(events = elemData.events) ) { - events = elemData.events = {}; - } - if ( !(eventHandle = elemData.handle) ) { - eventHandle = elemData.handle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? - jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : - undefined; - }; - // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events - eventHandle.elem = elem; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( core_rnotwhite ) || [""]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !(handlers = events[ type ]) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener/attachEvent if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - var j, handleObj, tmp, - origCount, t, events, - special, handlers, type, - namespaces, origType, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ); - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( core_rnotwhite ) || [""]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - jQuery._removeData( elem, "events" ); - } - }, - - trigger: function( event, data, elem, onlyHandlers ) { - var handle, ontype, cur, - bubbleType, special, tmp, i, - eventPath = [ elem || document ], - type = core_hasOwn.call( event, "type" ) ? event.type : event, - namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; - - cur = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf(".") >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf(":") < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join("."); - event.namespace_re = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === (elem.ownerDocument || document) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { - - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { - event.preventDefault(); - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && - jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - try { - elem[ type ](); - } catch ( e ) { - // IE<9 dies on focus/blur to hidden element (#1486,#12518) - // only reproducible on winXP IE8 native, not IE9 in IE8 mode - } - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event ); - - var i, ret, handleObj, matched, j, - handlerQueue = [], - args = core_slice.call( arguments ), - handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( (event.result = ret) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var sel, handleObj, matches, i, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - // Black-hole SVG instance trees (#13180) - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { - - /* jshint eqeqeq: false */ - for ( ; cur != this; cur = cur.parentNode || this ) { - /* jshint eqeqeq: true */ - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matches[ sel ] === undefined ) { - matches[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) >= 0 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matches[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, handlers: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( delegateCount < handlers.length ) { - handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); - } - - return handlerQueue; - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[ type ]; - - if ( !fixHook ) { - this.fixHooks[ type ] = fixHook = - rmouseEvent.test( type ) ? this.mouseHooks : - rkeyEvent.test( type ) ? this.keyHooks : - {}; - } - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = new jQuery.Event( originalEvent ); - - i = copy.length; - while ( i-- ) { - prop = copy[ i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Support: IE<9 - // Fix target property (#1925) - if ( !event.target ) { - event.target = originalEvent.srcElement || document; - } - - // Support: Chrome 23+, Safari? - // Target should not be a text node (#504, #13143) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // Support: IE<9 - // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) - event.metaKey = !!event.metaKey; - - return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var body, eventDoc, doc, - button = original.button, - fromElement = original.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && fromElement ) { - event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - try { - this.focus(); - return false; - } catch ( e ) { - // Support: IE<9 - // If we error on focus to hidden element (#1486, #12518), - // let .trigger() run the handlers - } - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return jQuery.nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Even when returnValue equals to undefined Firefox will still show alert - if ( event.result !== undefined ) { - event.originalEvent.returnValue = event.result; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - var name = "on" + type; - - if ( elem.detachEvent ) { - - // #8545, #7054, preventing memory leaks for custom events in IE6-8 - // detachEvent needed property on element, by name of that event, to properly expose it to GC - if ( typeof elem[ name ] === core_strundefined ) { - elem[ name ] = null; - } - - elem.detachEvent( name, handle ); - } - }; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - if ( !e ) { - return; - } - - // If preventDefault exists, run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // Support: IE - // Otherwise set the returnValue property of the original event to false - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - if ( !e ) { - return; - } - // If stopPropagation exists, run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - - // Support: IE - // Set the cancelBubble property of the original event to true - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - } -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// IE submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Lazy-add a submit handler when a descendant form may potentially be submitted - jQuery.event.add( this, "click._submit keypress._submit", function( e ) { - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; - if ( form && !jQuery._data( form, "submitBubbles" ) ) { - jQuery.event.add( form, "submit._submit", function( event ) { - event._submit_bubble = true; - }); - jQuery._data( form, "submitBubbles", true ); - } - }); - // return undefined since we don't need an event listener - }, - - postDispatch: function( event ) { - // If form was submitted by the user, bubble the event up the tree - if ( event._submit_bubble ) { - delete event._submit_bubble; - if ( this.parentNode && !event.isTrigger ) { - jQuery.event.simulate( "submit", this.parentNode, event, true ); - } - } - }, - - teardown: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - jQuery.event.remove( this, "._submit" ); - } - }; -} - -// IE change delegation and checkbox/radio fix -if ( !jQuery.support.changeBubbles ) { - - jQuery.event.special.change = { - - setup: function() { - - if ( rformElems.test( this.nodeName ) ) { - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if ( this.type === "checkbox" || this.type === "radio" ) { - jQuery.event.add( this, "propertychange._change", function( event ) { - if ( event.originalEvent.propertyName === "checked" ) { - this._just_changed = true; - } - }); - jQuery.event.add( this, "click._change", function( event ) { - if ( this._just_changed && !event.isTrigger ) { - this._just_changed = false; - } - // Allow triggered, simulated change events (#11500) - jQuery.event.simulate( "change", this, event, true ); - }); - } - return false; - } - // Delegated event; lazy-add a change handler on descendant inputs - jQuery.event.add( this, "beforeactivate._change", function( e ) { - var elem = e.target; - - if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { - jQuery.event.add( elem, "change._change", function( event ) { - if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { - jQuery.event.simulate( "change", this.parentNode, event, true ); - } - }); - jQuery._data( elem, "changeBubbles", true ); - } - }); - }, - - handle: function( event ) { - var elem = event.target; - - // Swallow native change events from checkbox/radio, we already triggered them above - if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { - return event.handleObj.handler.apply( this, arguments ); - } - }, - - teardown: function() { - jQuery.event.remove( this, "._change" ); - - return !rformElems.test( this.nodeName ); - } - }; -} - -// Create "bubbling" focus and blur events -if ( !jQuery.support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler while someone wants focusin/focusout - var attaches = 0, - handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - if ( attaches++ === 0 ) { - document.addEventListener( orig, handler, true ); - } - }, - teardown: function() { - if ( --attaches === 0 ) { - document.removeEventListener( orig, handler, true ); - } - } - }; - }); -} - -jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var type, origFn; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return this.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - var elem = this[0]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -}); -var isSimple = /^.[^:#\[\.,]*$/, - rparentsprev = /^(?:parents|prev(?:Until|All))/, - rneedsContext = jQuery.expr.match.needsContext, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var i, - ret = [], - self = this, - len = self.length; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }) ); - } - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - - has: function( target ) { - var i, - targets = jQuery( target, this ), - len = targets.length; - - return this.filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector || [], true) ); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector || [], false) ); - }, - - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - ret = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( ; i < l; i++ ) { - for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { - // Always skip document fragments - if ( cur.nodeType < 11 && (pos ? - pos.index(cur) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector(cur, selectors)) ) { - - cur = ret.push( cur ); - break; - } - } - } - - return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return jQuery.inArray( this[0], jQuery( elem ) ); - } - - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( jQuery.unique(all) ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } -}); - -function sibling( cur, dir ) { - do { - cur = cur[ dir ]; - } while ( cur && cur.nodeType !== 1 ); - - return cur; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - if ( this.length > 1 ) { - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - ret = jQuery.unique( ret ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - } - - return this.pushStack( ret ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : - jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - })); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - /* jshint -W018 */ - return !!qualifier.call( elem, i, elem ) !== not; - }); - - } - - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - }); - - } - - if ( typeof qualifier === "string" ) { - if ( isSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } - - qualifier = jQuery.filter( qualifier, elements ); - } - - return jQuery.grep( elements, function( elem ) { - return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; - }); -} -function createSafeFragment( document ) { - var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); - - if ( safeFrag.createElement ) { - while ( list.length ) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; -} - -var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, - rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rtbody = /\s*$/g, - - // We have to close these tags to support XHTML (#13200) - wrapMap = { - option: [ 1, "" ], - legend: [ 1, "
      ", "
      " ], - area: [ 1, "", "" ], - param: [ 1, "", "" ], - thead: [ 1, "", "
      " ], - tr: [ 2, "", "
      " ], - col: [ 2, "", "
      " ], - td: [ 3, "", "
      " ], - - // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, - // unless wrapped in a div with non-breaking characters in front of it. - _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
      ", "
      " ] - }, - safeFragment = createSafeFragment( document ), - fragmentDiv = safeFragment.appendChild( document.createElement("div") ); - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -jQuery.fn.extend({ - text: function( value ) { - return jQuery.access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); - }, null, value, arguments.length ); - }, - - append: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - }); - }, - - prepend: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - }); - }, - - before: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - }); - }, - - after: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - }); - }, - - // keepData is for internal use only--do not document - remove: function( selector, keepData ) { - var elem, - elems = selector ? jQuery.filter( selector, this ) : this, - i = 0; - - for ( ; (elem = elems[i]) != null; i++ ) { - - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem ) ); - } - - if ( elem.parentNode ) { - if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { - setGlobalEval( getAll( elem, "script" ) ); - } - elem.parentNode.removeChild( elem ); - } - } - - return this; - }, - - empty: function() { - var elem, - i = 0; - - for ( ; (elem = this[i]) != null; i++ ) { - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - } - - // Remove any remaining nodes - while ( elem.firstChild ) { - elem.removeChild( elem.firstChild ); - } - - // If this is a select, ensure that it displays empty (#12336) - // Support: IE<9 - if ( elem.options && jQuery.nodeName( elem, "select" ) ) { - elem.options.length = 0; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function () { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - }); - }, - - html: function( value ) { - return jQuery.access( this, function( value ) { - var elem = this[0] || {}, - i = 0, - l = this.length; - - if ( value === undefined ) { - return elem.nodeType === 1 ? - elem.innerHTML.replace( rinlinejQuery, "" ) : - undefined; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && - ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && - !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { - - value = value.replace( rxhtmlTag, "<$1>" ); - - try { - for (; i < l; i++ ) { - // Remove element nodes and prevent memory leaks - elem = this[i] || {}; - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch(e) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var - // Snapshot the DOM in case .domManip sweeps something relevant into its fragment - args = jQuery.map( this, function( elem ) { - return [ elem.nextSibling, elem.parentNode ]; - }), - i = 0; - - // Make the changes, replacing each context element with the new content - this.domManip( arguments, function( elem ) { - var next = args[ i++ ], - parent = args[ i++ ]; - - if ( parent ) { - // Don't use the snapshot next if it has moved (#13810) - if ( next && next.parentNode !== parent ) { - next = this.nextSibling; - } - jQuery( this ).remove(); - parent.insertBefore( elem, next ); - } - // Allow new content to include elements from the context set - }, true ); - - // Force removal if there was no new content (e.g., from empty arguments) - return i ? this : this.remove(); - }, - - detach: function( selector ) { - return this.remove( selector, true ); - }, - - domManip: function( args, callback, allowIntersection ) { - - // Flatten any nested arrays - args = core_concat.apply( [], args ); - - var first, node, hasScripts, - scripts, doc, fragment, - i = 0, - l = this.length, - set = this, - iNoClone = l - 1, - value = args[0], - isFunction = jQuery.isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { - return this.each(function( index ) { - var self = set.eq( index ); - if ( isFunction ) { - args[0] = value.call( this, index, self.html() ); - } - self.domManip( args, callback, allowIntersection ); - }); - } - - if ( l ) { - fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - if ( first ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( this[i], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { - - if ( node.src ) { - // Hope ajax is available... - jQuery._evalUrl( node.src ); - } else { - jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); - } - } - } - } - - // Fix #11809: Avoid leaking memory - fragment = first = null; - } - } - - return this; - } -}); - -// Support: IE<8 -// Manipulating tables requires a tbody -function manipulationTarget( elem, content ) { - return jQuery.nodeName( elem, "table" ) && - jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? - - elem.getElementsByTagName("tbody")[0] || - elem.appendChild( elem.ownerDocument.createElement("tbody") ) : - elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - var match = rscriptTypeMasked.exec( elem.type ); - if ( match ) { - elem.type = match[1]; - } else { - elem.removeAttribute("type"); - } - return elem; -} - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var elem, - i = 0; - for ( ; (elem = elems[i]) != null; i++ ) { - jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); - } -} - -function cloneCopyEvent( src, dest ) { - - if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { - return; - } - - var type, i, l, - oldData = jQuery._data( src ), - curData = jQuery._data( dest, oldData ), - events = oldData.events; - - if ( events ) { - delete curData.handle; - curData.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - - // make the cloned public data object a copy from the original - if ( curData.data ) { - curData.data = jQuery.extend( {}, curData.data ); - } -} - -function fixCloneNodeIssues( src, dest ) { - var nodeName, e, data; - - // We do not need to do anything for non-Elements - if ( dest.nodeType !== 1 ) { - return; - } - - nodeName = dest.nodeName.toLowerCase(); - - // IE6-8 copies events bound via attachEvent when using cloneNode. - if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { - data = jQuery._data( dest ); - - for ( e in data.events ) { - jQuery.removeEvent( dest, e, data.handle ); - } - - // Event data gets referenced instead of copied if the expando gets copied too - dest.removeAttribute( jQuery.expando ); - } - - // IE blanks contents when cloning scripts, and tries to evaluate newly-set text - if ( nodeName === "script" && dest.text !== src.text ) { - disableScript( dest ).text = src.text; - restoreScript( dest ); - - // IE6-10 improperly clones children of object elements using classid. - // IE10 throws NoModificationAllowedError if parent is null, #12132. - } else if ( nodeName === "object" ) { - if ( dest.parentNode ) { - dest.outerHTML = src.outerHTML; - } - - // This path appears unavoidable for IE9. When cloning an object - // element in IE9, the outerHTML strategy above is not sufficient. - // If the src has innerHTML and the destination does not, - // copy the src.innerHTML into the dest.innerHTML. #10324 - if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { - dest.innerHTML = src.innerHTML; - } - - } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { - // IE6-8 fails to persist the checked state of a cloned checkbox - // or radio button. Worse, IE6-7 fail to give the cloned element - // a checked appearance if the defaultChecked value isn't also set - - dest.defaultChecked = dest.checked = src.checked; - - // IE6-7 get confused and end up setting the value of a cloned - // checkbox/radio button to an empty string instead of "on" - if ( dest.value !== src.value ) { - dest.value = src.value; - } - - // IE6-8 fails to return the selected option to the default selected - // state when cloning options - } else if ( nodeName === "option" ) { - dest.defaultSelected = dest.selected = src.defaultSelected; - - // IE6-8 fails to set the defaultValue to the correct value when - // cloning other types of input fields - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - i = 0, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone(true); - jQuery( insert[i] )[ original ]( elems ); - - // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() - core_push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -}); - -function getAll( context, tag ) { - var elems, elem, - i = 0, - found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : - typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : - undefined; - - if ( !found ) { - for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { - if ( !tag || jQuery.nodeName( elem, tag ) ) { - found.push( elem ); - } else { - jQuery.merge( found, getAll( elem, tag ) ); - } - } - } - - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], found ) : - found; -} - -// Used in buildFragment, fixes the defaultChecked property -function fixDefaultChecked( elem ) { - if ( manipulation_rcheckableType.test( elem.type ) ) { - elem.defaultChecked = elem.checked; - } -} - -jQuery.extend({ - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var destElements, node, clone, i, srcElements, - inPage = jQuery.contains( elem.ownerDocument, elem ); - - if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { - clone = elem.cloneNode( true ); - - // IE<=8 does not properly clone detached, unknown element nodes - } else { - fragmentDiv.innerHTML = elem.outerHTML; - fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); - } - - if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && - (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - // Fix all IE cloning issues - for ( i = 0; (node = srcElements[i]) != null; ++i ) { - // Ensure that the destination node is not null; Fixes #9587 - if ( destElements[i] ) { - fixCloneNodeIssues( node, destElements[i] ); - } - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0; (node = srcElements[i]) != null; i++ ) { - cloneCopyEvent( node, destElements[i] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - destElements = srcElements = node = null; - - // Return the cloned set - return clone; - }, - - buildFragment: function( elems, context, scripts, selection ) { - var j, elem, contains, - tmp, tag, tbody, wrap, - l = elems.length, - - // Ensure a safe fragment - safe = createSafeFragment( context ), - - nodes = [], - i = 0; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || safe.appendChild( context.createElement("div") ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - - tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; - - // Descend through wrappers to the right content - j = wrap[0]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Manually add leading whitespace removed by IE - if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { - nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); - } - - // Remove IE's autoinserted from table fragments - if ( !jQuery.support.tbody ) { - - // String was a , *may* have spurious - elem = tag === "table" && !rtbody.test( elem ) ? - tmp.firstChild : - - // String was a bare or - wrap[1] === "
      " && !rtbody.test( elem ) ? - tmp : - 0; - - j = elem && elem.childNodes.length; - while ( j-- ) { - if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { - elem.removeChild( tbody ); - } - } - } - - jQuery.merge( nodes, tmp.childNodes ); - - // Fix #12392 for WebKit and IE > 9 - tmp.textContent = ""; - - // Fix #12392 for oldIE - while ( tmp.firstChild ) { - tmp.removeChild( tmp.firstChild ); - } - - // Remember the top-level container for proper cleanup - tmp = safe.lastChild; - } - } - } - - // Fix #11356: Clear elements from fragment - if ( tmp ) { - safe.removeChild( tmp ); - } - - // Reset defaultChecked for any radios and checkboxes - // about to be appended to the DOM in IE 6/7 (#8060) - if ( !jQuery.support.appendChecked ) { - jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); - } - - i = 0; - while ( (elem = nodes[ i++ ]) ) { - - // #4087 - If origin and destination elements are the same, and this is - // that element, do not do anything - if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( safe.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( (elem = tmp[ j++ ]) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - tmp = null; - - return safe; - }, - - cleanData: function( elems, /* internal */ acceptData ) { - var elem, type, id, data, - i = 0, - internalKey = jQuery.expando, - cache = jQuery.cache, - deleteExpando = jQuery.support.deleteExpando, - special = jQuery.event.special; - - for ( ; (elem = elems[i]) != null; i++ ) { - - if ( acceptData || jQuery.acceptData( elem ) ) { - - id = elem[ internalKey ]; - data = id && cache[ id ]; - - if ( data ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Remove cache only if it was not already removed by jQuery.event.remove - if ( cache[ id ] ) { - - delete cache[ id ]; - - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( deleteExpando ) { - delete elem[ internalKey ]; - - } else if ( typeof elem.removeAttribute !== core_strundefined ) { - elem.removeAttribute( internalKey ); - - } else { - elem[ internalKey ] = null; - } - - core_deletedIds.push( id ); - } - } - } - } - }, - - _evalUrl: function( url ) { - return jQuery.ajax({ - url: url, - type: "GET", - dataType: "script", - async: false, - global: false, - "throws": true - }); - } -}); -jQuery.fn.extend({ - wrapAll: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapAll( html.call(this, i) ); - }); - } - - if ( this[0] ) { - // The elements to wrap the target around - var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); - - if ( this[0].parentNode ) { - wrap.insertBefore( this[0] ); - } - - wrap.map(function() { - var elem = this; - - while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { - elem = elem.firstChild; - } - - return elem; - }).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapInner( html.call(this, i) ); - }); - } - - return this.each(function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - }); - }, - - wrap: function( html ) { - var isFunction = jQuery.isFunction( html ); - - return this.each(function(i) { - jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); - }); - }, - - unwrap: function() { - return this.parent().each(function() { - if ( !jQuery.nodeName( this, "body" ) ) { - jQuery( this ).replaceWith( this.childNodes ); - } - }).end(); - } -}); -var iframe, getStyles, curCSS, - ralpha = /alpha\([^)]*\)/i, - ropacity = /opacity\s*=\s*([^)]*)/, - rposition = /^(top|right|bottom|left)$/, - // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" - // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rmargin = /^margin/, - rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), - rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), - rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), - elemdisplay = { BODY: "block" }, - - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: 0, - fontWeight: 400 - }, - - cssExpand = [ "Top", "Right", "Bottom", "Left" ], - cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; - -// return a css property mapped to a potentially vendor prefixed property -function vendorPropName( style, name ) { - - // shortcut for names that are not vendor prefixed - if ( name in style ) { - return name; - } - - // check for vendor prefixed names - var capName = name.charAt(0).toUpperCase() + name.slice(1), - origName = name, - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in style ) { - return name; - } - } - - return origName; -} - -function isHidden( elem, el ) { - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); -} - -function showHide( elements, show ) { - var display, elem, hidden, - values = [], - index = 0, - length = elements.length; - - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - values[ index ] = jQuery._data( elem, "olddisplay" ); - display = elem.style.display; - if ( show ) { - // Reset the inline display of this element to learn if it is - // being hidden by cascaded rules or not - if ( !values[ index ] && display === "none" ) { - elem.style.display = ""; - } - - // Set elements which have been overridden with display: none - // in a stylesheet to whatever the default browser style is - // for such an element - if ( elem.style.display === "" && isHidden( elem ) ) { - values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); - } - } else { - - if ( !values[ index ] ) { - hidden = isHidden( elem ); - - if ( display && display !== "none" || !hidden ) { - jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); - } - } - } - } - - // Set the display of most of the elements in a second loop - // to avoid the constant reflow - for ( index = 0; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - if ( !show || elem.style.display === "none" || elem.style.display === "" ) { - elem.style.display = show ? values[ index ] || "" : "none"; - } - } - - return elements; -} - -jQuery.fn.extend({ - css: function( name, value ) { - return jQuery.access( this, function( elem, name, value ) { - var len, styles, - map = {}, - i = 0; - - if ( jQuery.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; - - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } - - return map; - } - - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - }, - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } - - return this.each(function() { - if ( isHidden( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - }); - } -}); - -jQuery.extend({ - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "columnCount": true, - "fillOpacity": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: { - // normalize float css property - "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" - }, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = jQuery.camelCase( name ), - style = elem.style; - - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // convert relative number strings (+= or -=) to relative numbers. #7345 - if ( type === "string" && (ret = rrelNum.exec( value )) ) { - value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); - // Fixes bug #9237 - type = "number"; - } - - // Make sure that NaN and null values aren't set. See: #7116 - if ( value == null || type === "number" && isNaN( value ) ) { - return; - } - - // If a number was passed in, add 'px' to the (except for certain CSS properties) - if ( type === "number" && !jQuery.cssNumber[ origName ] ) { - value += "px"; - } - - // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, - // but it would mean to define eight (for every problematic property) identical functions - if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { - style[ name ] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { - - // Wrapped to prevent IE from throwing errors when 'invalid' values are provided - // Fixes bug #5509 - try { - style[ name ] = value; - } catch(e) {} - } - - } else { - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, extra, styles ) { - var num, val, hooks, - origName = jQuery.camelCase( name ); - - // Make sure that we're working with the right name - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } - - //convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Return, converting to number if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; - } - return val; - } -}); - -// NOTE: we've included the "window" in window.getComputedStyle -// because jsdom on node.js will break without it. -if ( window.getComputedStyle ) { - getStyles = function( elem ) { - return window.getComputedStyle( elem, null ); - }; - - curCSS = function( elem, name, _computed ) { - var width, minWidth, maxWidth, - computed = _computed || getStyles( elem ), - - // getPropertyValue is only needed for .css('filter') in IE9, see #12537 - ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, - style = elem.style; - - if ( computed ) { - - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right - // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels - // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values - if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret; - }; -} else if ( document.documentElement.currentStyle ) { - getStyles = function( elem ) { - return elem.currentStyle; - }; - - curCSS = function( elem, name, _computed ) { - var left, rs, rsLeft, - computed = _computed || getStyles( elem ), - ret = computed ? computed[ name ] : undefined, - style = elem.style; - - // Avoid setting ret to empty string here - // so we don't default to auto - if ( ret == null && style && style[ name ] ) { - ret = style[ name ]; - } - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - // but not position css attributes, as those are proportional to the parent element instead - // and we can't measure the parent instead because it might trigger a "stacking dolls" problem - if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { - - // Remember the original values - left = style.left; - rs = elem.runtimeStyle; - rsLeft = rs && rs.left; - - // Put in the new values to get a computed value out - if ( rsLeft ) { - rs.left = elem.currentStyle.left; - } - style.left = name === "fontSize" ? "1em" : ret; - ret = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - if ( rsLeft ) { - rs.left = rsLeft; - } - } - - return ret === "" ? "auto" : ret; - }; -} - -function setPositiveNumber( elem, value, subtract ) { - var matches = rnumsplit.exec( value ); - return matches ? - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : - value; -} - -function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { - var i = extra === ( isBorderBox ? "border" : "content" ) ? - // If we already have the right measurement, avoid augmentation - 4 : - // Otherwise initialize for horizontal or vertical properties - name === "width" ? 1 : 0, - - val = 0; - - for ( ; i < 4; i += 2 ) { - // both box models exclude margin, so add it if we want it - if ( extra === "margin" ) { - val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); - } - - if ( isBorderBox ) { - // border-box includes padding, so remove it if we want content - if ( extra === "content" ) { - val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // at this point, extra isn't border nor margin, so remove border - if ( extra !== "margin" ) { - val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } else { - // at this point, extra isn't content, so add padding - val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // at this point, extra isn't content nor padding, so add border - if ( extra !== "padding" ) { - val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - return val; -} - -function getWidthOrHeight( elem, name, extra ) { - - // Start with offset property, which is equivalent to the border-box value - var valueIsBorderBox = true, - val = name === "width" ? elem.offsetWidth : elem.offsetHeight, - styles = getStyles( elem ), - isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; - - // some non-html elements return undefined for offsetWidth, so check for null/undefined - // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 - // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 - if ( val <= 0 || val == null ) { - // Fall back to computed then uncomputed css if necessary - val = curCSS( elem, name, styles ); - if ( val < 0 || val == null ) { - val = elem.style[ name ]; - } - - // Computed unit is not pixels. Stop here and return. - if ( rnumnonpx.test(val) ) { - return val; - } - - // we need the check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); - - // Normalize "", auto, and prepare for extra - val = parseFloat( val ) || 0; - } - - // use the active box-sizing model to add/subtract irrelevant styles - return ( val + - augmentWidthOrHeight( - elem, - name, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles - ) - ) + "px"; -} - -// Try to determine the default display value of an element -function css_defaultDisplay( nodeName ) { - var doc = document, - display = elemdisplay[ nodeName ]; - - if ( !display ) { - display = actualDisplay( nodeName, doc ); - - // If the simple way fails, read from inside an iframe - if ( display === "none" || !display ) { - // Use the already-created iframe if possible - iframe = ( iframe || - jQuery(" - - - - -
      -
      -

      - Mattia Larentis · Peter Stein · Emanuele Marchi -

      - - -
      -
      -
      -
      -
      - - - - - -
      -
      -

      Change the size programmatically:

      - -
      -
      - - - - -
      -
      <input type="checkbox" checked class="switch-large">
      -<input type="checkbox" checked>
      -<input type="checkbox" checked class="switch-small">
      -<input type="checkbox" checked class="switch-mini">
      -<input id="dimension-switch" type="checkbox" checked>
      -
      // Resets to the regular style
      -$('#dimension-switch').bootstrapSwitch('setSizeClass', '');
      -
      -// Sets a mini switch
      -$('#dimension-switch').bootstrapSwitch('setSizeClass', 'switch-mini');
      -
      -// Sets a small switch
      -$('#dimension-switch').bootstrapSwitch('setSizeClass', 'switch-small');
      -
      -// Sets a large switch
      -$('#dimension-switch').bootstrapSwitch('setSizeClass', 'switch-large');
      -
      -
      - - - - - - - -
      -
      - Change the colors programmatically: - -
      -
      - - -
      <input type="checkbox" checked data-on="primary" data-off="info">
      -<input type="checkbox" checked data-on="info" data-off="success">
      -<input type="checkbox" checked data-on="success" data-off="warning">
      -<input type="checkbox" checked data-on="warning" data-off="danger">
      -<input type="checkbox" checked data-on="danger" data-off="default">
      -<input type="checkbox" checked data-on="default" data-off="primary">
      -<input type="checkbox" id="change-color-switch" checked data-on="default" data-off="primary">
      -
      $('#change-color-switch').bootstrapSwitch('setOnClass', 'success');
      -$('#change-color-switch').bootstrapSwitch('setOffClass', 'danger');
      -
      -
      - - -
      -
      - - -
      <input type="checkbox" checked data-animated="false">
      -
      // Enables animation for the selected item
      -$('#animated-switch').bootstrapSwitch('setAnimated', true);
      -
      -// Disables animation for the selected item
      -$('#animated-switch').bootstrapSwitch('setAnimated', false);
      -
      -
      - - - -
      <input type="checkbox" checked disabled>
      -<input type="checkbox" checked readonly>
      -
      -
      - - -
      -
      - - -
      <input type="checkbox" checked data-on-label="SI" data-off-label="NO">
      -
      $('#label-switch').bootstrapSwitch('setOnLabel', 'I');
      -$('#label-switch').bootstrapSwitch('setOffLabel', 'O');
      -
      - -
      - -
      -
      <input type="checkbox" checked data-text-label="TV">
      - -
      - -
      -
      <input type="checkbox" checked data-on-label="<i class='icon-ok icon-white'></i>" data-off-label="<i class='icon-remove'></i>">
      - -
      - Standard    - Font Awesome    - Flat UI -
      -
      <input type="checkbox" checked class="switch-large" data-label-icon="icon-fullscreen" data-on-label="<i class='icon-ok icon-white'></i>" data-off-label="<i class='icon-remove'></i>">
      -<input type="checkbox" checked class="switch-large" data-label-icon="icon-youtube icon-large" data-on-label="<i class='icon-thumbs-up icon-white'></i>" data-off-label="<i class='icon-thumbs-down'></i>">
      -<input type="checkbox" class="switch-large" checked data-label-icon="fui-video" data-on-label="<i class='fui-check icon-white'></i>" data-off-label="<i class='fui-cross'></i>">
      - -
      - -
      -
      $('#switch-change').on('switch-change', function (e, data) {
      -  var $element = $(data.el),
      -      value = data.value;
      -
      -  console.log(e, $element, value);
      -});
      - -
      - - -
      -
      <label id="label-toggle-switch">Click on this Text to change the switch state</label>
      -<input type="checkbox" checked>
      -
      $('#label-toggle-switch').on('click', function(e, data) {
      -    $('.label-toggle-switch').bootstrapSwitch('toggleState');
      -});
      -$('.label-toggle-switch').on('switch-change', function (e, data) {
      -    alert(data.value);
      -});
      - -
      - -
      -
      -
      State!
      -
      On
      -
      Toggle
      -
      Off
      -
      -
      $('#toggle-state-switch').bootstrapSwitch('state'); // true || false
      -$('#toggle-state-switch').bootstrapSwitch('toggleState');
      -$('#toggle-state-switch').bootstrapSwitch('setState', false); // true || false
      - -
      - -
      -
      - -
      -
      $('#destroy-switch').bootstrapSwitch('destroy');
      - -
      - -
      -
      -
      Create
      -
      -
      $('#create-switch').bootstrapSwitch();
      - -
      - - -
      -
      - - - - -
      -
      - - -
      -
      - - - - -
      -
      $('#disable-switch').bootstrapSwitch('isDisabled');
      -$('#disable-switch').bootstrapSwitch('toggleDisabled');
      -$('#disable-switch').bootstrapSwitch('setDisabled', true);  // true || false
      -
      -$('#readonly-switch').bootstrapSwitch('isReadOnly');
      -$('#readonly-switch').bootstrapSwitch('toggleReadOnly');
      -$('#readonly-switch').bootstrapSwitch('setReadOnly', true);  // true || false
      - -
      -
      - -    - -    - - -
      -
      -
      <div class="form-group">
      -  <label for="option1">Option 1</label>
      -  <input id="option1" type="radio" name="radio1" value="option1">
      -  <label for="option2">Option 2</label>
      -  <input id="option2" type="radio" name="radio1" value="option2">
      -  <label for="option3">Option 3</label>
      -  <input id="option3" type="radio" name="radio1" value="option3">
      -</div>
      -
      $('.radio1').on('switch-change', function () {
      -    $('.radio1').bootstrapSwitch('toggleRadioState');
      -});
      -
      -// or
      -$('.radio1').on('switch-change', function () {
      -    $('.radio1').bootstrapSwitch('toggleRadioStateAllowUncheck');
      -});
      -
      -// or
      -$('.radio1').on('switch-change', function () {
      -    $('.radio1').bootstrapSwitch('toggleRadioStateAllowUncheck', false);
      -});
      - -
      -
      - - - - - - -
      -
      -
      <div class="form-group">
      -  <label for="option11">Option 1</label>
      -  <input id="option11" type="radio" name="radio2" value="option1">
      -  <label for="option12">Option 2</label>
      -  <input id="option12" type="radio" name="radio2" value="option2" checked="checked">
      -  <label for="option13">Option 3</label>
      -  <input id="option13" type="radio" name="radio2" value="option3">
      -</div>
      -
      $('.radio2').on('switch-change', function () {
      -    $('.radio2').bootstrapSwitch('toggleRadioStateAllowUncheck', true);
      -});
      - -
      -
      -
      - - -
      -
      - - -
      -
      - - -
      -
      - -
      - -
      -
      -
      <form class="form-horizontal">
      -  <div class="form-group">
      -    <label class="control-label" for="inputEmail">Email</label>
      -    <input type="text" id="inputEmail" placeholder="Email">
      -  </div>
      -  <div class="form-group">
      -    <label class="control-label" for="notification1">Notification 1</label>
      -    <input id="notification1" type="checkbox">
      -  </div>
      -  <div class="form-group">
      -    <label class="control-label" for="notification2">Notification 2</label>
      -    <input id="notification2" type="checkbox">
      -  </div>
      -  <div class="form-actions">
      -    <button type="reset" class="btn btn-inverse">Reset</button>
      -  </div>
      -</form>
      - -
      - Modal -
      -
      <a href="#myModal" role="button" class="btn btn-default" data-toggle="modal">Modal</a>
      -
      -<div class="modal-body">
      -  <input type="checkbox" checked>
      -</div>
      - -
      -
      -
      - - - - - - - - diff --git a/dist/bower_components/bootstrap-switch/package.json b/dist/bower_components/bootstrap-switch/package.json deleted file mode 100644 index f9aa5bf09..000000000 --- a/dist/bower_components/bootstrap-switch/package.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "bootstrap-switch", - "description": "Turn checkboxes and radio buttons in toggle switches.", - "version": "2.0.1", - "keywords": [ - "bootstrap", - "switch", - "javascript", - "js" - ], - "homepage": "http://www.bootstrap-switch.org", - "author": { - "name": "Mattia Larentis", - "email": "sorich87@gmail.com", - "url": "http://larentis.eu" - }, - "contributors": [ - { - "name": "Emanuele Marchi", - "email": "emanuele@lostcrew.it", - "url": "http://lostcrew.it" - }, - { - "name": "Peter Stein", - "url": "http://www.bdmdesign.org" - } - ], - "main": "build/js/bootstrap-switch.js", - "dependencies": { - "jquery": ">=1.9.0" - }, - "repository": { - "type": "git", - "url": "git://github.com/nostalgiaz/bootstrap-switch.git" - }, - "bugs": "https://github.com/nostalgiaz/bootstrap-switch/issues", - "license": "Apache Version 2", - "readmeFilename": "README.md", - "devDependencies": { - "matchdep": "~0.3.0", - "grunt": "~0.4.2", - "grunt-contrib-less": "~0.8.3", - "grunt-contrib-jshint": "~0.7.2", - "grunt-bump": "0.0.11", - "grunt-contrib-coffee": "~0.7.0", - "grunt-contrib-uglify": "~0.2.7", - "grunt-contrib-cssmin": "~0.7.0", - "grunt-coffeelint": "0.0.8", - "grunt-banner": "~0.2.0", - "grunt-contrib-watch": "~0.5.3", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-connect": "~0.6.0", - "grunt-open": "~0.2.2" - } -} diff --git a/dist/bower_components/bootstrap-switch/src/coffee/bootstrap-switch.coffee b/dist/bower_components/bootstrap-switch/src/coffee/bootstrap-switch.coffee deleted file mode 100644 index 7997ee125..000000000 --- a/dist/bower_components/bootstrap-switch/src/coffee/bootstrap-switch.coffee +++ /dev/null @@ -1,340 +0,0 @@ -(($) -> - $.fn.bootstrapSwitch = (method) -> - methods = - init: -> - @each -> - $element = $(@) - $switchLeft = $("", - class: "switch-left" - html: -> - html = "ON" - label = $element.data("on-label") - html = label if label? - html - ) - $switchRight = $("", - class: "switch-right" - html: -> - html = "OFF" - label = $element.data("off-label") - html = label if label? - html - ) - $label = $("\s*$/g,At={option:[1,""],legend:[1,"
      ","
      "],area:[1,"",""],param:[1,"",""],thead:[1,"
      `s and ``s.\n@table-cell-padding: 8px;\n//** Padding for cells in `.table-condensed`.\n@table-condensed-cell-padding: 5px;\n\n//** Default background color used for all tables.\n@table-bg: transparent;\n//** Background color used for `.table-striped`.\n@table-bg-accent: #f9f9f9;\n//** Background color used for `.table-hover`.\n@table-bg-hover: #f5f5f5;\n@table-bg-active: @table-bg-hover;\n\n//** Border color for table and cell borders.\n@table-border-color: #ddd;\n\n\n//== Buttons\n//\n//## For each of Bootstrap's buttons, define text, background and border color.\n\n@btn-font-weight: normal;\n\n@btn-default-color: #333;\n@btn-default-bg: #fff;\n@btn-default-border: #ccc;\n\n@btn-primary-color: #fff;\n@btn-primary-bg: @brand-primary;\n@btn-primary-border: darken(@btn-primary-bg, 5%);\n\n@btn-success-color: #fff;\n@btn-success-bg: @brand-success;\n@btn-success-border: darken(@btn-success-bg, 5%);\n\n@btn-info-color: #fff;\n@btn-info-bg: @brand-info;\n@btn-info-border: darken(@btn-info-bg, 5%);\n\n@btn-warning-color: #fff;\n@btn-warning-bg: @brand-warning;\n@btn-warning-border: darken(@btn-warning-bg, 5%);\n\n@btn-danger-color: #fff;\n@btn-danger-bg: @brand-danger;\n@btn-danger-border: darken(@btn-danger-bg, 5%);\n\n@btn-link-disabled-color: @gray-light;\n\n\n//== Forms\n//\n//##\n\n//** `` background color\n@input-bg: #fff;\n//** `` background color\n@input-bg-disabled: @gray-lighter;\n\n//** Text color for ``s\n@input-color: @gray;\n//** `` border color\n@input-border: #ccc;\n//** `` border radius\n@input-border-radius: @border-radius-base;\n//** Border color for inputs on focus\n@input-border-focus: #66afe9;\n\n//** Placeholder text color\n@input-color-placeholder: @gray-light;\n\n//** Default `.form-control` height\n@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);\n//** Large `.form-control` height\n@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\n//** Small `.form-control` height\n@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);\n\n@legend-color: @gray-dark;\n@legend-border-color: #e5e5e5;\n\n//** Background color for textual input addons\n@input-group-addon-bg: @gray-lighter;\n//** Border color for textual input addons\n@input-group-addon-border-color: @input-border;\n\n\n//== Dropdowns\n//\n//## Dropdown menu container and contents.\n\n//** Background for the dropdown menu.\n@dropdown-bg: #fff;\n//** Dropdown menu `border-color`.\n@dropdown-border: rgba(0,0,0,.15);\n//** Dropdown menu `border-color` **for IE8**.\n@dropdown-fallback-border: #ccc;\n//** Divider color for between dropdown items.\n@dropdown-divider-bg: #e5e5e5;\n\n//** Dropdown link text color.\n@dropdown-link-color: @gray-dark;\n//** Hover color for dropdown links.\n@dropdown-link-hover-color: darken(@gray-dark, 5%);\n//** Hover background for dropdown links.\n@dropdown-link-hover-bg: #f5f5f5;\n\n//** Active dropdown menu item text color.\n@dropdown-link-active-color: @component-active-color;\n//** Active dropdown menu item background color.\n@dropdown-link-active-bg: @component-active-bg;\n\n//** Disabled dropdown menu item background color.\n@dropdown-link-disabled-color: @gray-light;\n\n//** Text color for headers within dropdown menus.\n@dropdown-header-color: @gray-light;\n\n// Note: Deprecated @dropdown-caret-color as of v3.1.0\n@dropdown-caret-color: #000;\n\n\n//-- Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n//\n// Note: These variables are not generated into the Customizer.\n\n@zindex-navbar: 1000;\n@zindex-dropdown: 1000;\n@zindex-popover: 1010;\n@zindex-tooltip: 1030;\n@zindex-navbar-fixed: 1030;\n@zindex-modal-background: 1040;\n@zindex-modal: 1050;\n\n\n//== Media queries breakpoints\n//\n//## Define the breakpoints at which your layout will change, adapting to different screen sizes.\n\n// Extra small screen / phone\n// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1\n@screen-xs: 480px;\n@screen-xs-min: @screen-xs;\n@screen-phone: @screen-xs-min;\n\n// Small screen / tablet\n// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1\n@screen-sm: 768px;\n@screen-sm-min: @screen-sm;\n@screen-tablet: @screen-sm-min;\n\n// Medium screen / desktop\n// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1\n@screen-md: 992px;\n@screen-md-min: @screen-md;\n@screen-desktop: @screen-md-min;\n\n// Large screen / wide desktop\n// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1\n@screen-lg: 1200px;\n@screen-lg-min: @screen-lg;\n@screen-lg-desktop: @screen-lg-min;\n\n// So media queries don't overlap when required, provide a maximum\n@screen-xs-max: (@screen-sm-min - 1);\n@screen-sm-max: (@screen-md-min - 1);\n@screen-md-max: (@screen-lg-min - 1);\n\n\n//== Grid system\n//\n//## Define your custom responsive grid.\n\n//** Number of columns in the grid.\n@grid-columns: 12;\n//** Padding between columns. Gets divided in half for the left and right.\n@grid-gutter-width: 30px;\n// Navbar collapse\n//** Point at which the navbar becomes uncollapsed.\n@grid-float-breakpoint: @screen-sm-min;\n//** Point at which the navbar begins collapsing.\n@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);\n\n\n//== Navbar\n//\n//##\n\n// Basics of a navbar\n@navbar-height: 50px;\n@navbar-margin-bottom: @line-height-computed;\n@navbar-border-radius: @border-radius-base;\n@navbar-padding-horizontal: floor((@grid-gutter-width / 2));\n@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);\n@navbar-collapse-max-height: 340px;\n\n@navbar-default-color: #777;\n@navbar-default-bg: #f8f8f8;\n@navbar-default-border: darken(@navbar-default-bg, 6.5%);\n\n// Navbar links\n@navbar-default-link-color: #777;\n@navbar-default-link-hover-color: #333;\n@navbar-default-link-hover-bg: transparent;\n@navbar-default-link-active-color: #555;\n@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);\n@navbar-default-link-disabled-color: #ccc;\n@navbar-default-link-disabled-bg: transparent;\n\n// Navbar brand label\n@navbar-default-brand-color: @navbar-default-link-color;\n@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%);\n@navbar-default-brand-hover-bg: transparent;\n\n// Navbar toggle\n@navbar-default-toggle-hover-bg: #ddd;\n@navbar-default-toggle-icon-bar-bg: #888;\n@navbar-default-toggle-border-color: #ddd;\n\n\n// Inverted navbar\n// Reset inverted navbar basics\n@navbar-inverse-color: @gray-light;\n@navbar-inverse-bg: #222;\n@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);\n\n// Inverted navbar links\n@navbar-inverse-link-color: @gray-light;\n@navbar-inverse-link-hover-color: #fff;\n@navbar-inverse-link-hover-bg: transparent;\n@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;\n@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);\n@navbar-inverse-link-disabled-color: #444;\n@navbar-inverse-link-disabled-bg: transparent;\n\n// Inverted navbar brand label\n@navbar-inverse-brand-color: @navbar-inverse-link-color;\n@navbar-inverse-brand-hover-color: #fff;\n@navbar-inverse-brand-hover-bg: transparent;\n\n// Inverted navbar toggle\n@navbar-inverse-toggle-hover-bg: #333;\n@navbar-inverse-toggle-icon-bar-bg: #fff;\n@navbar-inverse-toggle-border-color: #333;\n\n\n//== Navs\n//\n//##\n\n//=== Shared nav styles\n@nav-link-padding: 10px 15px;\n@nav-link-hover-bg: @gray-lighter;\n\n@nav-disabled-link-color: @gray-light;\n@nav-disabled-link-hover-color: @gray-light;\n\n@nav-open-link-hover-color: #fff;\n\n//== Tabs\n@nav-tabs-border-color: #ddd;\n\n@nav-tabs-link-hover-border-color: @gray-lighter;\n\n@nav-tabs-active-link-hover-bg: @body-bg;\n@nav-tabs-active-link-hover-color: @gray;\n@nav-tabs-active-link-hover-border-color: #ddd;\n\n@nav-tabs-justified-link-border-color: #ddd;\n@nav-tabs-justified-active-link-border-color: @body-bg;\n\n//== Pills\n@nav-pills-border-radius: @border-radius-base;\n@nav-pills-active-link-hover-bg: @component-active-bg;\n@nav-pills-active-link-hover-color: @component-active-color;\n\n\n//== Pagination\n//\n//##\n\n@pagination-color: @link-color;\n@pagination-bg: #fff;\n@pagination-border: #ddd;\n\n@pagination-hover-color: @link-hover-color;\n@pagination-hover-bg: @gray-lighter;\n@pagination-hover-border: #ddd;\n\n@pagination-active-color: #fff;\n@pagination-active-bg: @brand-primary;\n@pagination-active-border: @brand-primary;\n\n@pagination-disabled-color: @gray-light;\n@pagination-disabled-bg: #fff;\n@pagination-disabled-border: #ddd;\n\n\n//== Pager\n//\n//##\n\n@pager-bg: @pagination-bg;\n@pager-border: @pagination-border;\n@pager-border-radius: 15px;\n\n@pager-hover-bg: @pagination-hover-bg;\n\n@pager-active-bg: @pagination-active-bg;\n@pager-active-color: @pagination-active-color;\n\n@pager-disabled-color: @pagination-disabled-color;\n\n\n//== Jumbotron\n//\n//##\n\n@jumbotron-padding: 30px;\n@jumbotron-color: inherit;\n@jumbotron-bg: @gray-lighter;\n@jumbotron-heading-color: inherit;\n@jumbotron-font-size: ceil((@font-size-base * 1.5));\n\n\n//== Form states and alerts\n//\n//## Define colors for form feedback states and, by default, alerts.\n\n@state-success-text: #3c763d;\n@state-success-bg: #dff0d8;\n@state-success-border: darken(spin(@state-success-bg, -10), 5%);\n\n@state-info-text: #31708f;\n@state-info-bg: #d9edf7;\n@state-info-border: darken(spin(@state-info-bg, -10), 7%);\n\n@state-warning-text: #8a6d3b;\n@state-warning-bg: #fcf8e3;\n@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);\n\n@state-danger-text: #a94442;\n@state-danger-bg: #f2dede;\n@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);\n\n\n//== Tooltips\n//\n//##\n\n//** Tooltip max width\n@tooltip-max-width: 200px;\n//** Tooltip text color\n@tooltip-color: #fff;\n//** Tooltip background color\n@tooltip-bg: #000;\n@tooltip-opacity: .9;\n\n//** Tooltip arrow width\n@tooltip-arrow-width: 5px;\n//** Tooltip arrow color\n@tooltip-arrow-color: @tooltip-bg;\n\n\n//== Popovers\n//\n//##\n\n//** Popover body background color\n@popover-bg: #fff;\n//** Popover maximum width\n@popover-max-width: 276px;\n//** Popover border color\n@popover-border-color: rgba(0,0,0,.2);\n//** Popover fallback border color\n@popover-fallback-border-color: #ccc;\n\n//** Popover title background color\n@popover-title-bg: darken(@popover-bg, 3%);\n\n//** Popover arrow width\n@popover-arrow-width: 10px;\n//** Popover arrow color\n@popover-arrow-color: #fff;\n\n//** Popover outer arrow width\n@popover-arrow-outer-width: (@popover-arrow-width + 1);\n//** Popover outer arrow color\n@popover-arrow-outer-color: rgba(0,0,0,.25);\n//** Popover outer arrow fallback color\n@popover-arrow-outer-fallback-color: #999;\n\n\n//== Labels\n//\n//##\n\n//** Default label background color\n@label-default-bg: @gray-light;\n//** Primary label background color\n@label-primary-bg: @brand-primary;\n//** Success label background color\n@label-success-bg: @brand-success;\n//** Info label background color\n@label-info-bg: @brand-info;\n//** Warning label background color\n@label-warning-bg: @brand-warning;\n//** Danger label background color\n@label-danger-bg: @brand-danger;\n\n//** Default label text color\n@label-color: #fff;\n//** Default text color of a linked label\n@label-link-hover-color: #fff;\n\n\n//== Modals\n//\n//##\n\n//** Padding applied to the modal body\n@modal-inner-padding: 20px;\n\n//** Padding applied to the modal title\n@modal-title-padding: 15px;\n//** Modal title line-height\n@modal-title-line-height: @line-height-base;\n\n//** Background color of modal content area\n@modal-content-bg: #fff;\n//** Modal content border color\n@modal-content-border-color: rgba(0,0,0,.2);\n//** Modal content border color **for IE8**\n@modal-content-fallback-border-color: #999;\n\n//** Modal backdrop background color\n@modal-backdrop-bg: #000;\n//** Modal backdrop opacity\n@modal-backdrop-opacity: .5;\n//** Modal header border color\n@modal-header-border-color: #e5e5e5;\n//** Modal footer border color\n@modal-footer-border-color: @modal-header-border-color;\n\n@modal-lg: 900px;\n@modal-md: 600px;\n@modal-sm: 300px;\n\n\n//== Alerts\n//\n//## Define alert colors, border radius, and padding.\n\n@alert-padding: 15px;\n@alert-border-radius: @border-radius-base;\n@alert-link-font-weight: bold;\n\n@alert-success-bg: @state-success-bg;\n@alert-success-text: @state-success-text;\n@alert-success-border: @state-success-border;\n\n@alert-info-bg: @state-info-bg;\n@alert-info-text: @state-info-text;\n@alert-info-border: @state-info-border;\n\n@alert-warning-bg: @state-warning-bg;\n@alert-warning-text: @state-warning-text;\n@alert-warning-border: @state-warning-border;\n\n@alert-danger-bg: @state-danger-bg;\n@alert-danger-text: @state-danger-text;\n@alert-danger-border: @state-danger-border;\n\n\n//== Progress bars\n//\n//##\n\n//** Background color of the whole progress component\n@progress-bg: #f5f5f5;\n//** Progress bar text color\n@progress-bar-color: #fff;\n\n//** Default progress bar color\n@progress-bar-bg: @brand-primary;\n//** Success progress bar color\n@progress-bar-success-bg: @brand-success;\n//** Warning progress bar color\n@progress-bar-warning-bg: @brand-warning;\n//** Danger progress bar color\n@progress-bar-danger-bg: @brand-danger;\n//** Info progress bar color\n@progress-bar-info-bg: @brand-info;\n\n\n//== List group\n//\n//##\n\n//** Background color on `.list-group-item`\n@list-group-bg: #fff;\n//** `.list-group-item` border color\n@list-group-border: #ddd;\n//** List group border radius\n@list-group-border-radius: @border-radius-base;\n\n//** Background color of single list elements on hover\n@list-group-hover-bg: #f5f5f5;\n//** Text color of active list elements\n@list-group-active-color: @component-active-color;\n//** Background color of active list elements\n@list-group-active-bg: @component-active-bg;\n//** Border color of active list elements\n@list-group-active-border: @list-group-active-bg;\n@list-group-active-text-color: lighten(@list-group-active-bg, 40%);\n\n@list-group-link-color: #555;\n@list-group-link-heading-color: #333;\n\n\n//== Panels\n//\n//##\n\n@panel-bg: #fff;\n@panel-body-padding: 15px;\n@panel-border-radius: @border-radius-base;\n\n//** Border color for elements within panels\n@panel-inner-border: #ddd;\n@panel-footer-bg: #f5f5f5;\n\n@panel-default-text: @gray-dark;\n@panel-default-border: #ddd;\n@panel-default-heading-bg: #f5f5f5;\n\n@panel-primary-text: #fff;\n@panel-primary-border: @brand-primary;\n@panel-primary-heading-bg: @brand-primary;\n\n@panel-success-text: @state-success-text;\n@panel-success-border: @state-success-border;\n@panel-success-heading-bg: @state-success-bg;\n\n@panel-info-text: @state-info-text;\n@panel-info-border: @state-info-border;\n@panel-info-heading-bg: @state-info-bg;\n\n@panel-warning-text: @state-warning-text;\n@panel-warning-border: @state-warning-border;\n@panel-warning-heading-bg: @state-warning-bg;\n\n@panel-danger-text: @state-danger-text;\n@panel-danger-border: @state-danger-border;\n@panel-danger-heading-bg: @state-danger-bg;\n\n\n//== Thumbnails\n//\n//##\n\n//** Padding around the thumbnail image\n@thumbnail-padding: 4px;\n//** Thumbnail background color\n@thumbnail-bg: @body-bg;\n//** Thumbnail border color\n@thumbnail-border: #ddd;\n//** Thumbnail border radius\n@thumbnail-border-radius: @border-radius-base;\n\n//** Custom text color for thumbnail captions\n@thumbnail-caption-color: @text-color;\n//** Padding around the thumbnail caption\n@thumbnail-caption-padding: 9px;\n\n\n//== Wells\n//\n//##\n\n@well-bg: #f5f5f5;\n@well-border: darken(@well-bg, 7%);\n\n\n//== Badges\n//\n//##\n\n@badge-color: #fff;\n//** Linked badge text color on hover\n@badge-link-hover-color: #fff;\n@badge-bg: @gray-light;\n\n//** Badge text color in active nav link\n@badge-active-color: @link-color;\n//** Badge background color in active nav link\n@badge-active-bg: #fff;\n\n@badge-font-weight: bold;\n@badge-line-height: 1;\n@badge-border-radius: 10px;\n\n\n//== Breadcrumbs\n//\n//##\n\n@breadcrumb-padding-vertical: 8px;\n@breadcrumb-padding-horizontal: 15px;\n//** Breadcrumb background color\n@breadcrumb-bg: #f5f5f5;\n//** Breadcrumb text color\n@breadcrumb-color: #ccc;\n//** Text color of current page in the breadcrumb\n@breadcrumb-active-color: @gray-light;\n//** Textual separator for between breadcrumb elements\n@breadcrumb-separator: \"/\";\n\n\n//== Carousel\n//\n//##\n\n@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);\n\n@carousel-control-color: #fff;\n@carousel-control-width: 15%;\n@carousel-control-opacity: .5;\n@carousel-control-font-size: 20px;\n\n@carousel-indicator-active-bg: #fff;\n@carousel-indicator-border-color: #fff;\n\n@carousel-caption-color: #fff;\n\n\n//== Close\n//\n//##\n\n@close-font-weight: bold;\n@close-color: #000;\n@close-text-shadow: 0 1px 0 #fff;\n\n\n//== Code\n//\n//##\n\n@code-color: #c7254e;\n@code-bg: #f9f2f4;\n\n@kbd-color: #fff;\n@kbd-bg: #333;\n\n@pre-bg: #f5f5f5;\n@pre-color: @gray-dark;\n@pre-border-color: #ccc;\n@pre-scrollable-max-height: 340px;\n\n\n//== Type\n//\n//##\n\n//** Text muted color\n@text-muted: @gray-light;\n//** Abbreviations and acronyms border color\n@abbr-border-color: @gray-light;\n//** Headings small color\n@headings-small-color: @gray-light;\n//** Blockquote small color\n@blockquote-small-color: @gray-light;\n//** Blockquote border color\n@blockquote-border-color: @gray-lighter;\n//** Page header border color\n@page-header-border-color: @gray-lighter;\n\n\n//== Miscellaneous\n//\n//##\n\n//** Horizontal line color.\n@hr-border: @gray-lighter;\n\n//** Horizontal offset for forms and lists.\n@component-offset-horizontal: 180px;\n\n\n//== Container sizes\n//\n//## Define the maximum width of `.container` for different screen sizes.\n\n// Small screen / tablet\n@container-tablet: ((720px + @grid-gutter-width));\n//** For `@screen-sm-min` and up.\n@container-sm: @container-tablet;\n\n// Medium screen / desktop\n@container-desktop: ((940px + @grid-gutter-width));\n//** For `@screen-md-min` and up.\n@container-md: @container-desktop;\n\n// Large screen / wide desktop\n@container-large-desktop: ((1140px + @grid-gutter-width));\n//** For `@screen-lg-min` and up.\n@container-lg: @container-large-desktop;\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 200;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: 14px base font * 85% = about 12px\nsmall,\n.small { font-size: 85%; }\n\n// Undo browser default styling\ncite { font-style: normal; }\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// --------------------------------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n\n &:first-child {\n padding-left: 0;\n }\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n@media (min-width: @grid-float-breakpoint) {\n .dl-horizontal {\n dt {\n float: left;\n width: (@component-offset-horizontal - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @component-offset-horizontal;\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n }\n}\n\n// MISC\n// ----\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: (@font-size-base * 1.25);\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n content: \"\";\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n white-space: nowrap;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid-columns-float(xs);\n.make-grid(@grid-columns, xs, width);\n.make-grid(@grid-columns, xs, pull);\n.make-grid(@grid-columns, xs, push);\n.make-grid(@grid-columns, xs, offset);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid-columns-float(sm);\n .make-grid(@grid-columns, sm, width);\n .make-grid(@grid-columns, sm, pull);\n .make-grid(@grid-columns, sm, push);\n .make-grid(@grid-columns, sm, offset);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid-columns-float(md);\n .make-grid(@grid-columns, md, width);\n .make-grid(@grid-columns, md, pull);\n .make-grid(@grid-columns, md, push);\n .make-grid(@grid-columns, md, offset);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid-columns-float(lg);\n .make-grid(@grid-columns, lg, width);\n .make-grid(@grid-columns, lg, pull);\n .make-grid(@grid-columns, lg, push);\n .make-grid(@grid-columns, lg, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n max-width: 100%;\n background-color: @table-bg;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-child(odd) {\n > td,\n > th {\n background-color: @table-bg-accent;\n }\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n > td,\n > th {\n background-color: @table-bg-hover;\n }\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n@media (max-width: @screen-xs-max) {\n .table-responsive {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n overflow-x: scroll;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n -webkit-overflow-scrolling: touch;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: -webkit-min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; /* IE8-9 */\n line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n // Note: HTML5 says that controls under a fieldset > legend:first-child won't\n // be disabled if the fieldset is disabled. Due to implementation difficulty,\n // we don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n cursor: not-allowed;\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n// Special styles for iOS date input\n//\n// In Mobile Safari, date inputs require a pixel line-height that matches the\n// given height of the input.\ninput[type=\"date\"] {\n line-height: @input-height-base;\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n display: block;\n min-height: @line-height-computed; // clear the floating input if there is no label text\n margin-top: 10px;\n margin-bottom: 10px;\n padding-left: 20px;\n label {\n display: inline;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n float: left;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"],\n.radio,\n.radio-inline,\n.checkbox,\n.checkbox-inline {\n &[disabled],\n fieldset[disabled] & {\n cursor: not-allowed;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\n.input-sm {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.input-lg {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n\n // Feedback icon (requires .glyphicon classes)\n .form-control-feedback {\n position: absolute;\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n right: 0;\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n }\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n margin-bottom: 0; // Remove default margin from `p`\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n display: block; // account for any element using help-block\n margin-top: 5px;\n margin-bottom: 10px;\n color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n // Kick in the inline\n @media (min-width: @screen-sm-min) {\n // Inline-block all the things for \"inline\"\n .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // In navbar-form, allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match (which also avoids\n // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n .radio,\n .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n vertical-align: middle;\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n float: none;\n margin-left: 0;\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n }\n }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n // Consistent vertical alignment of labels, radios, and checkboxes\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n .form-control-static {\n padding-top: (@padding-base-vertical + 1);\n }\n\n // Only right align form labels here when the columns stop stacking\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n right: (@grid-gutter-width / 2);\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n .user-select(none);\n\n &:focus {\n .tab-focus();\n }\n\n &:hover,\n &:focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: not-allowed;\n pointer-events: none; // Future-proof disabling of clicks\n .opacity(.65);\n .box-shadow(none);\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n cursor: pointer;\n border-radius: 0;\n\n &,\n &:active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: underline;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n padding-left: 0;\n padding-right: 0;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twitter/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n &.in {\n display: block;\n }\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition(height .35s ease);\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: ~\"url('@{icon-font-path}@{icon-font-name}.eot')\";\n src: ~\"url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.woff') format('woff')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype')\",\n ~\"url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg')\";\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base solid;\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: not-allowed;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base solid;\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 1px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n &:focus {\n // Remove focus outline when dropdown JS adds it after closing the menu\n outline: none;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { .btn-xs(); }\n.btn-group-sm > .btn { .btn-sm(); }\n.btn-group-lg > .btn { .btn-lg(); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n border-top-right-radius: @border-radius-base;\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n border-bottom-left-radius: @border-radius-base;\n .border-top-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n}\n\n\n// Checkbox and radio options\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n display: none;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn { .input-lg(); }\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn { .input-sm(); }\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @border-radius-base;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n max-height: @navbar-collapse-max-height;\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @line-height-computed;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: none;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right { .pull-right(); }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: 0;\n }\n }\n}\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: not-allowed;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: not-allowed;\n }\n }\n\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n &[href] {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base classes\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: baseline;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n .btn-xs & {\n top: 0;\n padding: 1px 5px;\n }\n}\n\n// Hover state, but only for links\na.badge {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n}\n\n// Account for counters in navs\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n .container & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: (@font-size-base * 4.5);\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n > img,\n a > img {\n .img-responsive();\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissable alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n.progress-striped .progress-bar {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n.progress.active .progress-bar {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n > .pull-left {\n margin-right: 10px;\n }\n > .pull-right {\n margin-left: 10px;\n }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on `s and ``s. -@table-cell-padding: 8px; -//** Padding for cells in `.table-condensed`. -@table-condensed-cell-padding: 5px; - -//** Default background color used for all tables. -@table-bg: transparent; -//** Background color used for `.table-striped`. -@table-bg-accent: #f9f9f9; -//** Background color used for `.table-hover`. -@table-bg-hover: #f5f5f5; -@table-bg-active: @table-bg-hover; - -//** Border color for table and cell borders. -@table-border-color: #ddd; - - -//== Buttons -// -//## For each of Bootstrap's buttons, define text, background and border color. - -@btn-font-weight: normal; - -@btn-default-color: #333; -@btn-default-bg: #fff; -@btn-default-border: #ccc; - -@btn-primary-color: #fff; -@btn-primary-bg: @brand-primary; -@btn-primary-border: darken(@btn-primary-bg, 5%); - -@btn-success-color: #fff; -@btn-success-bg: @brand-success; -@btn-success-border: darken(@btn-success-bg, 5%); - -@btn-info-color: #fff; -@btn-info-bg: @brand-info; -@btn-info-border: darken(@btn-info-bg, 5%); - -@btn-warning-color: #fff; -@btn-warning-bg: @brand-warning; -@btn-warning-border: darken(@btn-warning-bg, 5%); - -@btn-danger-color: #fff; -@btn-danger-bg: @brand-danger; -@btn-danger-border: darken(@btn-danger-bg, 5%); - -@btn-link-disabled-color: @gray-light; - - -//== Forms -// -//## - -//** `` background color -@input-bg: #fff; -//** `` background color -@input-bg-disabled: @gray-lighter; - -//** Text color for ``s -@input-color: @gray; -//** `` border color -@input-border: #ccc; -//** `` border radius -@input-border-radius: @border-radius-base; -//** Border color for inputs on focus -@input-border-focus: #66afe9; - -//** Placeholder text color -@input-color-placeholder: @gray-light; - -//** Default `.form-control` height -@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2); -//** Large `.form-control` height -@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2); -//** Small `.form-control` height -@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2); - -@legend-color: @gray-dark; -@legend-border-color: #e5e5e5; - -//** Background color for textual input addons -@input-group-addon-bg: @gray-lighter; -//** Border color for textual input addons -@input-group-addon-border-color: @input-border; - - -//== Dropdowns -// -//## Dropdown menu container and contents. - -//** Background for the dropdown menu. -@dropdown-bg: #fff; -//** Dropdown menu `border-color`. -@dropdown-border: rgba(0,0,0,.15); -//** Dropdown menu `border-color` **for IE8**. -@dropdown-fallback-border: #ccc; -//** Divider color for between dropdown items. -@dropdown-divider-bg: #e5e5e5; - -//** Dropdown link text color. -@dropdown-link-color: @gray-dark; -//** Hover color for dropdown links. -@dropdown-link-hover-color: darken(@gray-dark, 5%); -//** Hover background for dropdown links. -@dropdown-link-hover-bg: #f5f5f5; - -//** Active dropdown menu item text color. -@dropdown-link-active-color: @component-active-color; -//** Active dropdown menu item background color. -@dropdown-link-active-bg: @component-active-bg; - -//** Disabled dropdown menu item background color. -@dropdown-link-disabled-color: @gray-light; - -//** Text color for headers within dropdown menus. -@dropdown-header-color: @gray-light; - -// Note: Deprecated @dropdown-caret-color as of v3.1.0 -@dropdown-caret-color: #000; - - -//-- Z-index master list -// -// Warning: Avoid customizing these values. They're used for a bird's eye view -// of components dependent on the z-axis and are designed to all work together. -// -// Note: These variables are not generated into the Customizer. - -@zindex-navbar: 1000; -@zindex-dropdown: 1000; -@zindex-popover: 1010; -@zindex-tooltip: 1030; -@zindex-navbar-fixed: 1030; -@zindex-modal-background: 1040; -@zindex-modal: 1050; - - -//== Media queries breakpoints -// -//## Define the breakpoints at which your layout will change, adapting to different screen sizes. - -// Extra small screen / phone -// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1 -@screen-xs: 480px; -@screen-xs-min: @screen-xs; -@screen-phone: @screen-xs-min; - -// Small screen / tablet -// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1 -@screen-sm: 768px; -@screen-sm-min: @screen-sm; -@screen-tablet: @screen-sm-min; - -// Medium screen / desktop -// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1 -@screen-md: 992px; -@screen-md-min: @screen-md; -@screen-desktop: @screen-md-min; - -// Large screen / wide desktop -// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1 -@screen-lg: 1200px; -@screen-lg-min: @screen-lg; -@screen-lg-desktop: @screen-lg-min; - -// So media queries don't overlap when required, provide a maximum -@screen-xs-max: (@screen-sm-min - 1); -@screen-sm-max: (@screen-md-min - 1); -@screen-md-max: (@screen-lg-min - 1); - - -//== Grid system -// -//## Define your custom responsive grid. - -//** Number of columns in the grid. -@grid-columns: 12; -//** Padding between columns. Gets divided in half for the left and right. -@grid-gutter-width: 30px; -// Navbar collapse -//** Point at which the navbar becomes uncollapsed. -@grid-float-breakpoint: @screen-sm-min; -//** Point at which the navbar begins collapsing. -@grid-float-breakpoint-max: (@grid-float-breakpoint - 1); - - -//== Navbar -// -//## - -// Basics of a navbar -@navbar-height: 50px; -@navbar-margin-bottom: @line-height-computed; -@navbar-border-radius: @border-radius-base; -@navbar-padding-horizontal: floor((@grid-gutter-width / 2)); -@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2); -@navbar-collapse-max-height: 340px; - -@navbar-default-color: #777; -@navbar-default-bg: #f8f8f8; -@navbar-default-border: darken(@navbar-default-bg, 6.5%); - -// Navbar links -@navbar-default-link-color: #777; -@navbar-default-link-hover-color: #333; -@navbar-default-link-hover-bg: transparent; -@navbar-default-link-active-color: #555; -@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%); -@navbar-default-link-disabled-color: #ccc; -@navbar-default-link-disabled-bg: transparent; - -// Navbar brand label -@navbar-default-brand-color: @navbar-default-link-color; -@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%); -@navbar-default-brand-hover-bg: transparent; - -// Navbar toggle -@navbar-default-toggle-hover-bg: #ddd; -@navbar-default-toggle-icon-bar-bg: #888; -@navbar-default-toggle-border-color: #ddd; - - -// Inverted navbar -// Reset inverted navbar basics -@navbar-inverse-color: @gray-light; -@navbar-inverse-bg: #222; -@navbar-inverse-border: darken(@navbar-inverse-bg, 10%); - -// Inverted navbar links -@navbar-inverse-link-color: @gray-light; -@navbar-inverse-link-hover-color: #fff; -@navbar-inverse-link-hover-bg: transparent; -@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color; -@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%); -@navbar-inverse-link-disabled-color: #444; -@navbar-inverse-link-disabled-bg: transparent; - -// Inverted navbar brand label -@navbar-inverse-brand-color: @navbar-inverse-link-color; -@navbar-inverse-brand-hover-color: #fff; -@navbar-inverse-brand-hover-bg: transparent; - -// Inverted navbar toggle -@navbar-inverse-toggle-hover-bg: #333; -@navbar-inverse-toggle-icon-bar-bg: #fff; -@navbar-inverse-toggle-border-color: #333; - - -//== Navs -// -//## - -//=== Shared nav styles -@nav-link-padding: 10px 15px; -@nav-link-hover-bg: @gray-lighter; - -@nav-disabled-link-color: @gray-light; -@nav-disabled-link-hover-color: @gray-light; - -@nav-open-link-hover-color: #fff; - -//== Tabs -@nav-tabs-border-color: #ddd; - -@nav-tabs-link-hover-border-color: @gray-lighter; - -@nav-tabs-active-link-hover-bg: @body-bg; -@nav-tabs-active-link-hover-color: @gray; -@nav-tabs-active-link-hover-border-color: #ddd; - -@nav-tabs-justified-link-border-color: #ddd; -@nav-tabs-justified-active-link-border-color: @body-bg; - -//== Pills -@nav-pills-border-radius: @border-radius-base; -@nav-pills-active-link-hover-bg: @component-active-bg; -@nav-pills-active-link-hover-color: @component-active-color; - - -//== Pagination -// -//## - -@pagination-color: @link-color; -@pagination-bg: #fff; -@pagination-border: #ddd; - -@pagination-hover-color: @link-hover-color; -@pagination-hover-bg: @gray-lighter; -@pagination-hover-border: #ddd; - -@pagination-active-color: #fff; -@pagination-active-bg: @brand-primary; -@pagination-active-border: @brand-primary; - -@pagination-disabled-color: @gray-light; -@pagination-disabled-bg: #fff; -@pagination-disabled-border: #ddd; - - -//== Pager -// -//## - -@pager-bg: @pagination-bg; -@pager-border: @pagination-border; -@pager-border-radius: 15px; - -@pager-hover-bg: @pagination-hover-bg; - -@pager-active-bg: @pagination-active-bg; -@pager-active-color: @pagination-active-color; - -@pager-disabled-color: @pagination-disabled-color; - - -//== Jumbotron -// -//## - -@jumbotron-padding: 30px; -@jumbotron-color: inherit; -@jumbotron-bg: @gray-lighter; -@jumbotron-heading-color: inherit; -@jumbotron-font-size: ceil((@font-size-base * 1.5)); - - -//== Form states and alerts -// -//## Define colors for form feedback states and, by default, alerts. - -@state-success-text: #3c763d; -@state-success-bg: #dff0d8; -@state-success-border: darken(spin(@state-success-bg, -10), 5%); - -@state-info-text: #31708f; -@state-info-bg: #d9edf7; -@state-info-border: darken(spin(@state-info-bg, -10), 7%); - -@state-warning-text: #8a6d3b; -@state-warning-bg: #fcf8e3; -@state-warning-border: darken(spin(@state-warning-bg, -10), 5%); - -@state-danger-text: #a94442; -@state-danger-bg: #f2dede; -@state-danger-border: darken(spin(@state-danger-bg, -10), 5%); - - -//== Tooltips -// -//## - -//** Tooltip max width -@tooltip-max-width: 200px; -//** Tooltip text color -@tooltip-color: #fff; -//** Tooltip background color -@tooltip-bg: #000; -@tooltip-opacity: .9; - -//** Tooltip arrow width -@tooltip-arrow-width: 5px; -//** Tooltip arrow color -@tooltip-arrow-color: @tooltip-bg; - - -//== Popovers -// -//## - -//** Popover body background color -@popover-bg: #fff; -//** Popover maximum width -@popover-max-width: 276px; -//** Popover border color -@popover-border-color: rgba(0,0,0,.2); -//** Popover fallback border color -@popover-fallback-border-color: #ccc; - -//** Popover title background color -@popover-title-bg: darken(@popover-bg, 3%); - -//** Popover arrow width -@popover-arrow-width: 10px; -//** Popover arrow color -@popover-arrow-color: #fff; - -//** Popover outer arrow width -@popover-arrow-outer-width: (@popover-arrow-width + 1); -//** Popover outer arrow color -@popover-arrow-outer-color: rgba(0,0,0,.25); -//** Popover outer arrow fallback color -@popover-arrow-outer-fallback-color: #999; - - -//== Labels -// -//## - -//** Default label background color -@label-default-bg: @gray-light; -//** Primary label background color -@label-primary-bg: @brand-primary; -//** Success label background color -@label-success-bg: @brand-success; -//** Info label background color -@label-info-bg: @brand-info; -//** Warning label background color -@label-warning-bg: @brand-warning; -//** Danger label background color -@label-danger-bg: @brand-danger; - -//** Default label text color -@label-color: #fff; -//** Default text color of a linked label -@label-link-hover-color: #fff; - - -//== Modals -// -//## - -//** Padding applied to the modal body -@modal-inner-padding: 20px; - -//** Padding applied to the modal title -@modal-title-padding: 15px; -//** Modal title line-height -@modal-title-line-height: @line-height-base; - -//** Background color of modal content area -@modal-content-bg: #fff; -//** Modal content border color -@modal-content-border-color: rgba(0,0,0,.2); -//** Modal content border color **for IE8** -@modal-content-fallback-border-color: #999; - -//** Modal backdrop background color -@modal-backdrop-bg: #000; -//** Modal backdrop opacity -@modal-backdrop-opacity: .5; -//** Modal header border color -@modal-header-border-color: #e5e5e5; -//** Modal footer border color -@modal-footer-border-color: @modal-header-border-color; - -@modal-lg: 900px; -@modal-md: 600px; -@modal-sm: 300px; - - -//== Alerts -// -//## Define alert colors, border radius, and padding. - -@alert-padding: 15px; -@alert-border-radius: @border-radius-base; -@alert-link-font-weight: bold; - -@alert-success-bg: @state-success-bg; -@alert-success-text: @state-success-text; -@alert-success-border: @state-success-border; - -@alert-info-bg: @state-info-bg; -@alert-info-text: @state-info-text; -@alert-info-border: @state-info-border; - -@alert-warning-bg: @state-warning-bg; -@alert-warning-text: @state-warning-text; -@alert-warning-border: @state-warning-border; - -@alert-danger-bg: @state-danger-bg; -@alert-danger-text: @state-danger-text; -@alert-danger-border: @state-danger-border; - - -//== Progress bars -// -//## - -//** Background color of the whole progress component -@progress-bg: #f5f5f5; -//** Progress bar text color -@progress-bar-color: #fff; - -//** Default progress bar color -@progress-bar-bg: @brand-primary; -//** Success progress bar color -@progress-bar-success-bg: @brand-success; -//** Warning progress bar color -@progress-bar-warning-bg: @brand-warning; -//** Danger progress bar color -@progress-bar-danger-bg: @brand-danger; -//** Info progress bar color -@progress-bar-info-bg: @brand-info; - - -//== List group -// -//## - -//** Background color on `.list-group-item` -@list-group-bg: #fff; -//** `.list-group-item` border color -@list-group-border: #ddd; -//** List group border radius -@list-group-border-radius: @border-radius-base; - -//** Background color of single list elements on hover -@list-group-hover-bg: #f5f5f5; -//** Text color of active list elements -@list-group-active-color: @component-active-color; -//** Background color of active list elements -@list-group-active-bg: @component-active-bg; -//** Border color of active list elements -@list-group-active-border: @list-group-active-bg; -@list-group-active-text-color: lighten(@list-group-active-bg, 40%); - -@list-group-link-color: #555; -@list-group-link-heading-color: #333; - - -//== Panels -// -//## - -@panel-bg: #fff; -@panel-body-padding: 15px; -@panel-border-radius: @border-radius-base; - -//** Border color for elements within panels -@panel-inner-border: #ddd; -@panel-footer-bg: #f5f5f5; - -@panel-default-text: @gray-dark; -@panel-default-border: #ddd; -@panel-default-heading-bg: #f5f5f5; - -@panel-primary-text: #fff; -@panel-primary-border: @brand-primary; -@panel-primary-heading-bg: @brand-primary; - -@panel-success-text: @state-success-text; -@panel-success-border: @state-success-border; -@panel-success-heading-bg: @state-success-bg; - -@panel-info-text: @state-info-text; -@panel-info-border: @state-info-border; -@panel-info-heading-bg: @state-info-bg; - -@panel-warning-text: @state-warning-text; -@panel-warning-border: @state-warning-border; -@panel-warning-heading-bg: @state-warning-bg; - -@panel-danger-text: @state-danger-text; -@panel-danger-border: @state-danger-border; -@panel-danger-heading-bg: @state-danger-bg; - - -//== Thumbnails -// -//## - -//** Padding around the thumbnail image -@thumbnail-padding: 4px; -//** Thumbnail background color -@thumbnail-bg: @body-bg; -//** Thumbnail border color -@thumbnail-border: #ddd; -//** Thumbnail border radius -@thumbnail-border-radius: @border-radius-base; - -//** Custom text color for thumbnail captions -@thumbnail-caption-color: @text-color; -//** Padding around the thumbnail caption -@thumbnail-caption-padding: 9px; - - -//== Wells -// -//## - -@well-bg: #f5f5f5; -@well-border: darken(@well-bg, 7%); - - -//== Badges -// -//## - -@badge-color: #fff; -//** Linked badge text color on hover -@badge-link-hover-color: #fff; -@badge-bg: @gray-light; - -//** Badge text color in active nav link -@badge-active-color: @link-color; -//** Badge background color in active nav link -@badge-active-bg: #fff; - -@badge-font-weight: bold; -@badge-line-height: 1; -@badge-border-radius: 10px; - - -//== Breadcrumbs -// -//## - -@breadcrumb-padding-vertical: 8px; -@breadcrumb-padding-horizontal: 15px; -//** Breadcrumb background color -@breadcrumb-bg: #f5f5f5; -//** Breadcrumb text color -@breadcrumb-color: #ccc; -//** Text color of current page in the breadcrumb -@breadcrumb-active-color: @gray-light; -//** Textual separator for between breadcrumb elements -@breadcrumb-separator: "/"; - - -//== Carousel -// -//## - -@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6); - -@carousel-control-color: #fff; -@carousel-control-width: 15%; -@carousel-control-opacity: .5; -@carousel-control-font-size: 20px; - -@carousel-indicator-active-bg: #fff; -@carousel-indicator-border-color: #fff; - -@carousel-caption-color: #fff; - - -//== Close -// -//## - -@close-font-weight: bold; -@close-color: #000; -@close-text-shadow: 0 1px 0 #fff; - - -//== Code -// -//## - -@code-color: #c7254e; -@code-bg: #f9f2f4; - -@kbd-color: #fff; -@kbd-bg: #333; - -@pre-bg: #f5f5f5; -@pre-color: @gray-dark; -@pre-border-color: #ccc; -@pre-scrollable-max-height: 340px; - - -//== Type -// -//## - -//** Text muted color -@text-muted: @gray-light; -//** Abbreviations and acronyms border color -@abbr-border-color: @gray-light; -//** Headings small color -@headings-small-color: @gray-light; -//** Blockquote small color -@blockquote-small-color: @gray-light; -//** Blockquote border color -@blockquote-border-color: @gray-lighter; -//** Page header border color -@page-header-border-color: @gray-lighter; - - -//== Miscellaneous -// -//## - -//** Horizontal line color. -@hr-border: @gray-lighter; - -//** Horizontal offset for forms and lists. -@component-offset-horizontal: 180px; - - -//== Container sizes -// -//## Define the maximum width of `.container` for different screen sizes. - -// Small screen / tablet -@container-tablet: ((720px + @grid-gutter-width)); -//** For `@screen-sm-min` and up. -@container-sm: @container-tablet; - -// Medium screen / desktop -@container-desktop: ((940px + @grid-gutter-width)); -//** For `@screen-md-min` and up. -@container-md: @container-desktop; - -// Large screen / wide desktop -@container-large-desktop: ((1140px + @grid-gutter-width)); -//** For `@screen-lg-min` and up. -@container-lg: @container-large-desktop; diff --git a/dist/bower_components/bootstrap/less/wells.less b/dist/bower_components/bootstrap/less/wells.less deleted file mode 100644 index 15d072b0c..000000000 --- a/dist/bower_components/bootstrap/less/wells.less +++ /dev/null @@ -1,29 +0,0 @@ -// -// Wells -// -------------------------------------------------- - - -// Base class -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: @well-bg; - border: 1px solid @well-border; - border-radius: @border-radius-base; - .box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); - blockquote { - border-color: #ddd; - border-color: rgba(0,0,0,.15); - } -} - -// Sizes -.well-lg { - padding: 24px; - border-radius: @border-radius-large; -} -.well-sm { - padding: 9px; - border-radius: @border-radius-small; -} diff --git a/dist/bower_components/bootstrap/package.json b/dist/bower_components/bootstrap/package.json deleted file mode 100644 index 6b38c31ab..000000000 --- a/dist/bower_components/bootstrap/package.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "name": "bootstrap", - "description": "Sleek, intuitive, and powerful front-end framework for faster and easier web development.", - "version": "3.1.0", - "keywords": [ - "bootstrap", - "css" - ], - "homepage": "http://getbootstrap.com", - "author": "Twitter, Inc.", - "scripts": { - "test": "grunt test" - }, - "repository": { - "type": "git", - "url": "https://github.com/twbs/bootstrap.git" - }, - "bugs": { - "url": "https://github.com/twbs/bootstrap/issues" - }, - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/twbs/bootstrap/blob/master/LICENSE" - } - ], - "devDependencies": { - "browserstack-runner": "~0.0.15", - "btoa": "~1.1.1", - "canonical-json": "~0.0.3", - "grunt": "~0.4.2", - "grunt-banner": "~0.2.0", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-concat": "~0.3.0", - "grunt-contrib-connect": "~0.6.0", - "grunt-contrib-copy": "~0.5.0", - "grunt-contrib-csslint": "~0.2.0", - "grunt-contrib-cssmin": "~0.7.0", - "grunt-contrib-jade": "~0.9.1", - "grunt-contrib-jshint": "~0.8.0", - "grunt-contrib-less": "~0.9.0", - "grunt-contrib-qunit": "~0.4.0", - "grunt-contrib-uglify": "~0.3.0", - "grunt-contrib-watch": "~0.5.3", - "grunt-csscomb": "~2.0.1", - "grunt-exec": "0.4.3", - "grunt-html-validation": "~0.1.13", - "grunt-jekyll": "~0.4.1", - "grunt-jscs-checker": "~0.3.0", - "grunt-saucelabs": "~4.1.2", - "grunt-sed": "~0.1.1", - "load-grunt-tasks": "~0.3.0", - "markdown": "~0.5.0" - }, - "jspm": { - "main": "js/bootstrap", - "directories": { - "example": "examples", - "lib": "dist" - }, - "shim": { - "js/bootstrap": { - "imports": "jquery", - "exports": "$" - } - }, - "buildConfig": { - "uglify": true - } - } -} diff --git a/dist/bower_components/bootstrap/test-infra/README.md b/dist/bower_components/bootstrap/test-infra/README.md deleted file mode 100644 index 2ee7ed9ab..000000000 --- a/dist/bower_components/bootstrap/test-infra/README.md +++ /dev/null @@ -1,100 +0,0 @@ -## What does `s3_cache.py` do? - -### In general -`s3_cache.py` maintains a cache, stored in an Amazon S3 (Simple Storage Service) bucket, of a given directory whose contents are considered non-critical and are completely & solely determined by (and should be able to be regenerated from) a single given file. - -The SHA-256 hash of the single file is used as the key for the cache. The directory is stored as a gzipped tarball. - -All the tarballs are stored in S3's Reduced Redundancy Storage (RRS) storage class, since this is cheaper and the data is non-critical. - -`s3_cache.py` itself never deletes cache entries; deletion should either be done manually or using automatic S3 lifecycle rules on the bucket. - -Similar to git, `s3_cache.py` makes the assumption that [SHA-256 will effectively never have a collision](http://stackoverflow.com/questions/4014090/is-it-safe-to-ignore-the-possibility-of-sha-collisions-in-practice). - - -### For Bootstrap specifically -`s3_cache.py` is used to cache the npm packages that our Grunt tasks depend on and the RubyGems that Jekyll depends on. (Jekyll is needed to compile our docs to HTML so that we can run them thru an HTML5 validator.) - -For npm, the `node_modules` directory is cached based on our `npm-shrinkwrap.canonical.json` file. - -For RubyGems, the `gemdir` of the current RVM-selected Ruby is cached based on the `pseudo_Gemfile.lock` file generated by our Travis build script. -`pseudo_Gemfile.lock` contains the versions of Ruby and Jekyll that we're using (read our `.travis.yml` for details). - - -## Why is `s3_cache.py` necessary? -`s3_cache.py` is used to speed up Bootstrap's Travis builds. Installing npm packages and RubyGems used to take up a significant fraction of our total build times. Also, at the time that `s3_cache.py` was written, npm was occasionally unreliable. - -Travis does offer built-in caching on their paid plans, but this do-it-ourselves S3 solution is significantly cheaper since we only need caching and not Travis' other paid features. - - -## Setup - -### Overview -1. Create an Amazon Web Services (AWS) account. -2. Create an Identity & Access Management (IAM) user, and note their credentials. -3. Create an S3 bucket. -4. Set permissions on the bucket to grant the user read+write access. -5. Set the user credentials as secure Travis environment variables. - -### In detail -1. Create an AWS account. -2. Login to the [AWS Management Console](https://console.aws.amazon.com). -3. Go to the IAM Management Console. -4. Create a new user (named e.g. `travis-ci`) and generate an access key for them. Note both the Access Key ID and the Secret Access Key. -5. Note the user's ARN (Amazon Resource Name), which can be found in the "Summary" tab of the user browser. This will be of the form: `arn:aws:iam::XXXXXXXXXXXXXX:user/the-username-goes-here` -6. Note the user's access key, which can be found in the "Security Credentials" tab of the user browser. -7. Go to the S3 Management Console. -8. Create a new bucket. For a non-publicly-accessible bucket (like Bootstrap uses), it's recommended that the bucket name be random to increase security. On most *nix machines, you can easily generate a random UUID to use as the bucket name using Python: - - ```bash - python -c "import uuid; print(uuid.uuid4())" - ``` - -9. Determine and note what your bucket's ARN is. The ARN for an S3 bucket is of the form: `arn:aws:s3:::the-bucket-name-goes-here` -10. In the bucket's Properties pane, in the "Permissions" section, click the "Edit bucket policy" button. -11. Input and submit an IAM Policy that grants the user at least read+write rights to the bucket. AWS has a policy generator and some examples to help with crafting the policy. Here's the policy that Bootstrap uses, with the sensitive bits censored: - - ```json - { - "Version": "2012-10-17", - "Id": "PolicyTravisReadWriteNoAdmin", - "Statement": [ - { - "Sid": "StmtXXXXXXXXXXXXXX", - "Effect": "Allow", - "Principal": { - "AWS": "arn:aws:iam::XXXXXXXXXXXXXX:user/travis-ci" - }, - "Action": [ - "s3:AbortMultipartUpload", - "s3:GetObjectVersion", - "s3:ListBucket", - "s3:DeleteObject", - "s3:DeleteObjectVersion", - "s3:GetObject", - "s3:PutObject" - ], - "Resource": [ - "arn:aws:s3:::XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", - "arn:aws:s3:::XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/*" - ] - } - ] - } - ``` - -12. If you want deletion from the cache to be done automatically based on age (like Bootstrap does): In the bucket's Properties pane, in the "Lifecycle" section, add a rule to expire/delete files based on creation date. -13. Install the [`travis` RubyGem](https://github.com/travis-ci/travis): `gem install travis` -14. Encrypt the environment variables: - - ```bash - travis encrypt --repo twbs/bootstrap "AWS_ACCESS_KEY_ID=XXX" - travis encrypt --repo twbs/bootstrap "AWS_SECRET_ACCESS_KEY=XXX" - travis encrypt --repo twbs/bootstrap "TWBS_S3_BUCKET=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" - ``` - -14. Add the resulting secure environment variables to `.travis.yml`. - - -## Usage -Read `s3_cache.py`'s source code and Bootstrap's `.travis.yml` for how to invoke and make use of `s3_cache.py`. diff --git a/dist/bower_components/bootstrap/test-infra/npm-shrinkwrap.canonical.json b/dist/bower_components/bootstrap/test-infra/npm-shrinkwrap.canonical.json deleted file mode 100644 index 41b2e201a..000000000 --- a/dist/bower_components/bootstrap/test-infra/npm-shrinkwrap.canonical.json +++ /dev/null @@ -1 +0,0 @@ -{"dependencies":{"browserstack-runner":{"dependencies":{"browserstack":{"from":"browserstack@1.0.1","resolved":"https://registry.npmjs.org/browserstack/-/browserstack-1.0.1.tgz","version":"1.0.1"}},"from":"browserstack-runner@~0.0.15","resolved":"https://registry.npmjs.org/browserstack-runner/-/browserstack-runner-0.0.15.tgz","version":"0.0.15"},"btoa":{"from":"btoa@~1.1.1","version":"1.1.1"},"canonical-json":{"from":"canonical-json@~0.0.3","resolved":"https://registry.npmjs.org/canonical-json/-/canonical-json-0.0.3.tgz","version":"0.0.3"},"grunt":{"dependencies":{"async":{"from":"async@~0.1.22","version":"0.1.22"},"coffee-script":{"from":"coffee-script@~1.3.3","version":"1.3.3"},"colors":{"from":"colors@~0.6.0","version":"0.6.2"},"dateformat":{"from":"dateformat@1.0.2-1.2.3","resolved":"https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz","version":"1.0.2-1.2.3"},"eventemitter2":{"from":"eventemitter2@~0.4.9","version":"0.4.13"},"exit":{"from":"exit@~0.1.1","version":"0.1.2"},"findup-sync":{"dependencies":{"lodash":{"from":"lodash@~1.0.1","version":"1.0.1"}},"from":"findup-sync@~0.1.2","version":"0.1.2"},"getobject":{"from":"getobject@~0.1.0","version":"0.1.0"},"glob":{"dependencies":{"graceful-fs":{"from":"graceful-fs@~1.2.0","version":"1.2.3"},"inherits":{"from":"inherits@1","version":"1.0.0"}},"from":"glob@~3.1.21","version":"3.1.21"},"hooker":{"from":"hooker@~0.2.3","resolved":"https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz","version":"0.2.3"},"iconv-lite":{"from":"iconv-lite@~0.2.11","version":"0.2.11"},"js-yaml":{"dependencies":{"argparse":{"dependencies":{"underscore":{"from":"underscore@~1.4.3","version":"1.4.4"},"underscore.string":{"from":"underscore.string@~2.3.1","version":"2.3.3"}},"from":"argparse@~ 0.1.11","version":"0.1.15"},"esprima":{"from":"esprima@~ 1.0.2","version":"1.0.4"}},"from":"js-yaml@~2.0.5","version":"2.0.5"},"lodash":{"from":"lodash@~0.9.2","version":"0.9.2"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.11","version":"0.2.14"},"nopt":{"dependencies":{"abbrev":{"from":"abbrev@1","version":"1.0.4"}},"from":"nopt@~1.0.10","version":"1.0.10"},"rimraf":{"dependencies":{"graceful-fs":{"from":"graceful-fs@~1.1","version":"1.1.14"}},"from":"rimraf@~2.0.3","version":"2.0.3"},"underscore.string":{"from":"underscore.string@~2.2.1","version":"2.2.1"},"which":{"from":"which@~1.0.5","version":"1.0.5"}},"from":"grunt@~0.4.2","version":"0.4.2"},"grunt-banner":{"from":"grunt-banner@~0.2.0","version":"0.2.0"},"grunt-contrib-clean":{"dependencies":{"rimraf":{"from":"rimraf@~2.2.1","resolved":"https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz","version":"2.2.6"}},"from":"grunt-contrib-clean@~0.5.0","version":"0.5.0"},"grunt-contrib-concat":{"from":"grunt-contrib-concat@~0.3.0","version":"0.3.0"},"grunt-contrib-connect":{"dependencies":{"connect":{"dependencies":{"batch":{"from":"batch@0.5.0","resolved":"https://registry.npmjs.org/batch/-/batch-0.5.0.tgz","version":"0.5.0"},"buffer-crc32":{"from":"buffer-crc32@0.2.1","resolved":"https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz","version":"0.2.1"},"bytes":{"from":"bytes@0.2.1","resolved":"https://registry.npmjs.org/bytes/-/bytes-0.2.1.tgz","version":"0.2.1"},"cookie":{"from":"cookie@0.1.0","resolved":"https://registry.npmjs.org/cookie/-/cookie-0.1.0.tgz","version":"0.1.0"},"cookie-signature":{"from":"cookie-signature@1.0.1","resolved":"https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.1.tgz","version":"1.0.1"},"debug":{"from":"debug@~0.7.2","version":"0.7.4"},"fresh":{"from":"fresh@0.2.0","resolved":"https://registry.npmjs.org/fresh/-/fresh-0.2.0.tgz","version":"0.2.0"},"methods":{"from":"methods@0.1.0","resolved":"https://registry.npmjs.org/methods/-/methods-0.1.0.tgz","version":"0.1.0"},"multiparty":{"dependencies":{"readable-stream":{"dependencies":{"core-util-is":{"from":"core-util-is@~1.0.0","version":"1.0.1"},"debuglog":{"from":"debuglog@0.0.2","resolved":"https://registry.npmjs.org/debuglog/-/debuglog-0.0.2.tgz","version":"0.0.2"}},"from":"readable-stream@~1.1.9","version":"1.1.10"},"stream-counter":{"from":"stream-counter@~0.2.0","version":"0.2.0"}},"from":"multiparty@2.2.0","resolved":"https://registry.npmjs.org/multiparty/-/multiparty-2.2.0.tgz","version":"2.2.0"},"negotiator":{"from":"negotiator@0.3.0","resolved":"https://registry.npmjs.org/negotiator/-/negotiator-0.3.0.tgz","version":"0.3.0"},"pause":{"from":"pause@0.0.1","resolved":"https://registry.npmjs.org/pause/-/pause-0.0.1.tgz","version":"0.0.1"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"raw-body":{"from":"raw-body@1.1.2","resolved":"https://registry.npmjs.org/raw-body/-/raw-body-1.1.2.tgz","version":"1.1.2"},"send":{"dependencies":{"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"range-parser":{"from":"range-parser@0.0.4","resolved":"https://registry.npmjs.org/range-parser/-/range-parser-0.0.4.tgz","version":"0.0.4"}},"from":"send@0.1.4","resolved":"https://registry.npmjs.org/send/-/send-0.1.4.tgz","version":"0.1.4"},"uid2":{"from":"uid2@0.0.3","resolved":"https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz","version":"0.0.3"}},"from":"connect@~2.12.0","version":"2.12.0"},"connect-livereload":{"from":"connect-livereload@~0.3.0","version":"0.3.2"},"open":{"from":"open@0.0.4","resolved":"https://registry.npmjs.org/open/-/open-0.0.4.tgz","version":"0.0.4"}},"from":"grunt-contrib-connect@~0.6.0","version":"0.6.0"},"grunt-contrib-copy":{"from":"grunt-contrib-copy@~0.5.0","version":"0.5.0"},"grunt-contrib-csslint":{"dependencies":{"csslint":{"dependencies":{"parserlib":{"from":"parserlib@~0.2.2","resolved":"https://registry.npmjs.org/parserlib/-/parserlib-0.2.4.tgz","version":"0.2.4"}},"from":"csslint@~0.10.0","version":"0.10.0"}},"from":"grunt-contrib-csslint@~0.2.0","version":"0.2.0"},"grunt-contrib-cssmin":{"dependencies":{"clean-css":{"dependencies":{"commander":{"from":"commander@2.0.x","version":"2.0.0"}},"from":"clean-css@~2.0.0","version":"2.0.6"},"grunt-lib-contrib":{"dependencies":{"zlib-browserify":{"from":"zlib-browserify@0.0.1","resolved":"https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz","version":"0.0.1"}},"from":"grunt-lib-contrib@~0.6.0","version":"0.6.1"}},"from":"grunt-contrib-cssmin@~0.7.0","version":"0.7.0"},"grunt-contrib-jade":{"dependencies":{"grunt-lib-contrib":{"dependencies":{"zlib-browserify":{"from":"zlib-browserify@0.0.1","resolved":"https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz","version":"0.0.1"}},"from":"grunt-lib-contrib@~0.6.1","version":"0.6.1"},"jade":{"dependencies":{"character-parser":{"from":"character-parser@1.2.0","resolved":"https://registry.npmjs.org/character-parser/-/character-parser-1.2.0.tgz","version":"1.2.0"},"commander":{"from":"commander@2.0.0","resolved":"https://registry.npmjs.org/commander/-/commander-2.0.0.tgz","version":"2.0.0"},"constantinople":{"dependencies":{"uglify-js":{"dependencies":{"async":{"from":"async@~0.2.6","version":"0.2.9"},"optimist":{"dependencies":{"wordwrap":{"from":"wordwrap@~0.0.2","version":"0.0.2"}},"from":"optimist@~0.3.5","version":"0.3.7"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@~0.1.7","version":"0.1.31"},"uglify-to-browserify":{"from":"uglify-to-browserify@~1.0.0","version":"1.0.1"}},"from":"uglify-js@~2.4.0","resolved":"https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.9.tgz","version":"2.4.9"}},"from":"constantinople@~1.0.2","version":"1.0.2"},"mkdirp":{"from":"mkdirp@~0.3.5","resolved":"https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz","version":"0.3.5"},"monocle":{"dependencies":{"readdirp":{"dependencies":{"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@>=0.2.4","version":"0.2.14"}},"from":"readdirp@~0.2.3","version":"0.2.5"}},"from":"monocle@1.1.50","resolved":"https://registry.npmjs.org/monocle/-/monocle-1.1.50.tgz","version":"1.1.50"},"transformers":{"dependencies":{"css":{"dependencies":{"css-parse":{"from":"css-parse@1.0.4","resolved":"https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz","version":"1.0.4"},"css-stringify":{"from":"css-stringify@1.0.5","resolved":"https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz","version":"1.0.5"}},"from":"css@~1.0.8","version":"1.0.8"},"promise":{"dependencies":{"is-promise":{"from":"is-promise@~1","version":"1.0.0"}},"from":"promise@~2.0","version":"2.0.0"},"uglify-js":{"dependencies":{"optimist":{"dependencies":{"wordwrap":{"from":"wordwrap@~0.0.2","version":"0.0.2"}},"from":"optimist@~0.3.5","version":"0.3.7"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@~0.1.7","version":"0.1.31"}},"from":"uglify-js@~2.2.5","version":"2.2.5"}},"from":"transformers@2.1.0","resolved":"https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz","version":"2.1.0"},"with":{"dependencies":{"uglify-js":{"dependencies":{"async":{"from":"async@~0.2.6","version":"0.2.9"},"optimist":{"dependencies":{"wordwrap":{"from":"wordwrap@~0.0.2","version":"0.0.2"}},"from":"optimist@~0.3.5","version":"0.3.7"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@~0.1.7","version":"0.1.31"},"uglify-to-browserify":{"from":"uglify-to-browserify@~1.0.0","version":"1.0.1"}},"from":"uglify-js@2.4.0","resolved":"https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.0.tgz","version":"2.4.0"}},"from":"with@~2.0.0","version":"2.0.0"}},"from":"jade@~1.0.2","version":"1.0.2"},"lodash-node":{"from":"lodash-node@~2.4.1","version":"2.4.1"}},"from":"grunt-contrib-jade@~0.9.1","version":"0.9.1"},"grunt-contrib-jshint":{"dependencies":{"jshint":{"dependencies":{"cli":{"dependencies":{"glob":{"dependencies":{"inherits":{"from":"inherits@2","version":"2.0.1"}},"from":"glob@>= 3.1.4","version":"3.2.8"}},"from":"cli@0.4.x","version":"0.4.5"},"console-browserify":{"from":"console-browserify@0.1.x","version":"0.1.6"},"htmlparser2":{"dependencies":{"domelementtype":{"from":"domelementtype@1","version":"1.1.1"},"domhandler":{"from":"domhandler@2.1","version":"2.1.0"},"domutils":{"from":"domutils@1.1","version":"1.1.6"},"readable-stream":{"from":"readable-stream@1.0","version":"1.0.24"}},"from":"htmlparser2@3.3.x","version":"3.3.0"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@0.x.x","version":"0.2.14"},"shelljs":{"from":"shelljs@0.1.x","version":"0.1.4"},"underscore":{"from":"underscore@1.4.x","version":"1.4.4"}},"from":"jshint@~2.4.0","version":"2.4.1"}},"from":"grunt-contrib-jshint@~0.8.0","version":"0.8.0"},"grunt-contrib-less":{"dependencies":{"chalk":{"dependencies":{"ansi-styles":{"from":"ansi-styles@~1.0.0","version":"1.0.0"},"has-color":{"from":"has-color@~0.1.0","version":"0.1.2"},"strip-ansi":{"from":"strip-ansi@~0.1.0","version":"0.1.1"}},"from":"chalk@~0.4.0","version":"0.4.0"},"grunt-lib-contrib":{"dependencies":{"zlib-browserify":{"from":"zlib-browserify@0.0.1","resolved":"https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz","version":"0.0.1"}},"from":"grunt-lib-contrib@~0.6.1","version":"0.6.1"},"less":{"dependencies":{"clean-css":{"dependencies":{"commander":{"from":"commander@2.0.x","resolved":"https://registry.npmjs.org/commander/-/commander-2.0.0.tgz","version":"2.0.0"}},"from":"clean-css@2.0.x","version":"2.0.6"},"mime":{"from":"mime@1.2.x","version":"1.2.11"},"mkdirp":{"from":"mkdirp@~0.3.5","resolved":"https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz","version":"0.3.5"},"request":{"dependencies":{"aws-sign2":{"from":"aws-sign2@~0.5.0","version":"0.5.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"async":{"from":"async@~0.2.9","version":"0.2.9"},"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@~0.1.0","version":"0.1.2"},"hawk":{"dependencies":{"boom":{"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.9.x","version":"0.9.1"},"sntp":{"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~1.0.0","version":"1.0.0"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.10.0","version":"0.10.0"},"json-stringify-safe":{"from":"json-stringify-safe@~5.0.0","version":"5.0.0"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"tough-cookie":{"dependencies":{"punycode":{"from":"punycode@>=0.2.0","version":"1.2.3"}},"from":"tough-cookie@~0.9.15","version":"0.9.15"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@>=2.12.0","version":"2.31.0"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@0.1.x","version":"0.1.31"}},"from":"less@~1.6.0","resolved":"https://registry.npmjs.org/less/-/less-1.6.1.tgz","version":"1.6.1"}},"from":"grunt-contrib-less@~0.9.0","version":"0.9.0"},"grunt-contrib-qunit":{"dependencies":{"grunt-lib-phantomjs":{"dependencies":{"eventemitter2":{"from":"eventemitter2@~0.4.9","version":"0.4.13"},"phantomjs":{"dependencies":{"adm-zip":{"from":"adm-zip@0.2.1","resolved":"https://registry.npmjs.org/adm-zip/-/adm-zip-0.2.1.tgz","version":"0.2.1"},"kew":{"from":"kew@~0.1.7","version":"0.1.7"},"mkdirp":{"from":"mkdirp@0.3.5","resolved":"https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz","version":"0.3.5"},"ncp":{"from":"ncp@0.4.2","resolved":"https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz","version":"0.4.2"},"npmconf":{"dependencies":{"config-chain":{"dependencies":{"proto-list":{"from":"proto-list@~1.2.1","version":"1.2.2"}},"from":"config-chain@~1.1.1","version":"1.1.8"},"inherits":{"from":"inherits@~1.0.0","version":"1.0.0"},"ini":{"from":"ini@~1.1.0","version":"1.1.0"},"nopt":{"dependencies":{"abbrev":{"from":"abbrev@1","version":"1.0.4"}},"from":"nopt@2","version":"2.1.2"},"once":{"from":"once@~1.1.1","version":"1.1.1"},"osenv":{"from":"osenv@0.0.3","resolved":"https://registry.npmjs.org/osenv/-/osenv-0.0.3.tgz","version":"0.0.3"},"semver":{"from":"semver@~1.1.0","version":"1.1.4"}},"from":"npmconf@0.0.24","resolved":"https://registry.npmjs.org/npmconf/-/npmconf-0.0.24.tgz","version":"0.0.24"},"rimraf":{"from":"rimraf@~2.2.2","version":"2.2.6"},"which":{"from":"which@~1.0.5","version":"1.0.5"}},"from":"phantomjs@~1.9.0-1","resolved":"https://registry.npmjs.org/phantomjs/-/phantomjs-1.9.7-1.tgz","version":"1.9.7-1"},"semver":{"from":"semver@~1.0.14","version":"1.0.14"},"temporary":{"dependencies":{"package":{"from":"package@>= 1.0.0 < 1.2.0","version":"1.0.1"}},"from":"temporary@~0.0.4","version":"0.0.8"}},"from":"grunt-lib-phantomjs@~0.5.0","resolved":"https://registry.npmjs.org/grunt-lib-phantomjs/-/grunt-lib-phantomjs-0.5.0.tgz","version":"0.5.0"}},"from":"grunt-contrib-qunit@~0.4.0","resolved":"https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-0.4.0.tgz","version":"0.4.0"},"grunt-contrib-uglify":{"dependencies":{"chalk":{"dependencies":{"ansi-styles":{"from":"ansi-styles@~1.0.0","version":"1.0.0"},"has-color":{"from":"has-color@~0.1.0","version":"0.1.2"},"strip-ansi":{"from":"strip-ansi@~0.1.0","version":"0.1.1"}},"from":"chalk@~0.4.0","version":"0.4.0"},"grunt-lib-contrib":{"dependencies":{"zlib-browserify":{"from":"zlib-browserify@0.0.1","resolved":"https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz","version":"0.0.1"}},"from":"grunt-lib-contrib@~0.6.1","version":"0.6.1"},"uglify-js":{"dependencies":{"async":{"from":"async@~0.2.6","resolved":"https://registry.npmjs.org/async/-/async-0.2.10.tgz","version":"0.2.10"},"optimist":{"dependencies":{"wordwrap":{"from":"wordwrap@~0.0.2","version":"0.0.2"}},"from":"optimist@~0.3.5","version":"0.3.7"},"source-map":{"dependencies":{"amdefine":{"from":"amdefine@>=0.0.4","version":"0.1.0"}},"from":"source-map@~0.1.7","version":"0.1.31"},"uglify-to-browserify":{"from":"uglify-to-browserify@~1.0.0","version":"1.0.1"}},"from":"uglify-js@~2.4.0","resolved":"https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.12.tgz","version":"2.4.12"}},"from":"grunt-contrib-uglify@~0.3.0","resolved":"https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-0.3.2.tgz","version":"0.3.2"},"grunt-contrib-watch":{"dependencies":{"gaze":{"dependencies":{"globule":{"dependencies":{"glob":{"dependencies":{"graceful-fs":{"from":"graceful-fs@~1.2.0","version":"1.2.3"},"inherits":{"from":"inherits@1","version":"1.0.0"}},"from":"glob@~3.1.21","version":"3.1.21"},"lodash":{"from":"lodash@~1.0.1","version":"1.0.1"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.11","version":"0.2.14"}},"from":"globule@~0.1.0","version":"0.1.0"}},"from":"gaze@~0.4.0","version":"0.4.3"},"tiny-lr":{"dependencies":{"debug":{"from":"debug@~0.7.2","version":"0.7.4"},"faye-websocket":{"from":"faye-websocket@~0.4.3","version":"0.4.4"},"noptify":{"dependencies":{"nopt":{"dependencies":{"abbrev":{"from":"abbrev@1","version":"1.0.4"}},"from":"nopt@~2.0.0","version":"2.0.0"}},"from":"noptify@latest","version":"0.0.3"},"qs":{"from":"qs@~0.5.2","version":"0.5.6"}},"from":"tiny-lr@0.0.4","resolved":"https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.0.4.tgz","version":"0.0.4"}},"from":"grunt-contrib-watch@~0.5.3","version":"0.5.3"},"grunt-csscomb":{"dependencies":{"csscomb":{"dependencies":{"commander":{"from":"commander@2.0.0","resolved":"https://registry.npmjs.org/commander/-/commander-2.0.0.tgz","version":"2.0.0"},"gonzales-pe":{"from":"gonzales-pe@2.0.x","resolved":"https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-2.0.2.tgz","version":"2.0.2"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@0.2.12","resolved":"https://registry.npmjs.org/minimatch/-/minimatch-0.2.12.tgz","version":"0.2.12"},"vow":{"from":"vow@0.3.11","resolved":"https://registry.npmjs.org/vow/-/vow-0.3.11.tgz","version":"0.3.11"},"vow-fs":{"dependencies":{"node-uuid":{"from":"node-uuid@1.4.0","resolved":"https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.0.tgz","version":"1.4.0"},"vow-queue":{"from":"vow-queue@0.0.2","resolved":"https://registry.npmjs.org/vow-queue/-/vow-queue-0.0.2.tgz","version":"0.0.2"}},"from":"vow-fs@0.2.3","resolved":"https://registry.npmjs.org/vow-fs/-/vow-fs-0.2.3.tgz","version":"0.2.3"}},"from":"csscomb@~2.0.0","resolved":"https://registry.npmjs.org/csscomb/-/csscomb-2.0.4.tgz","version":"2.0.4"}},"from":"grunt-csscomb@~2.0.1","version":"2.0.1"},"grunt-exec":{"from":"grunt-exec@0.4.3","resolved":"https://registry.npmjs.org/grunt-exec/-/grunt-exec-0.4.3.tgz","version":"0.4.3"},"grunt-html-validation":{"dependencies":{"colors":{"from":"colors@~0.6.0","version":"0.6.2"},"request":{"dependencies":{"aws-sign":{"from":"aws-sign@~0.3.0","version":"0.3.0"},"cookie-jar":{"from":"cookie-jar@~0.3.0","version":"0.3.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"async":{"from":"async@~0.2.9","version":"0.2.9"},"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@~0.1.0","version":"0.1.2"},"hawk":{"dependencies":{"boom":{"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.9.x","version":"0.9.1"},"sntp":{"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~1.0.0","version":"1.0.0"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.10.0","version":"0.10.0"},"json-stringify-safe":{"from":"json-stringify-safe@~5.0.0","version":"5.0.0"},"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","version":"0.6.6"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@~2.27.0","version":"2.27.0"},"w3cjs":{"dependencies":{"commander":{"from":"commander@2.0.x","version":"2.0.0"},"superagent":{"dependencies":{"cookiejar":{"from":"cookiejar@1.3.0","resolved":"https://registry.npmjs.org/cookiejar/-/cookiejar-1.3.0.tgz","version":"1.3.0"},"debug":{"from":"debug@~0.7.2","version":"0.7.4"},"emitter-component":{"from":"emitter-component@1.0.0","resolved":"https://registry.npmjs.org/emitter-component/-/emitter-component-1.0.0.tgz","version":"1.0.0"},"formidable":{"from":"formidable@1.0.14","resolved":"https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz","version":"1.0.14"},"methods":{"from":"methods@0.0.1","resolved":"https://registry.npmjs.org/methods/-/methods-0.0.1.tgz","version":"0.0.1"},"mime":{"from":"mime@1.2.5","resolved":"https://registry.npmjs.org/mime/-/mime-1.2.5.tgz","version":"1.2.5"},"qs":{"from":"qs@0.6.5","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.5.tgz","version":"0.6.5"},"reduce-component":{"from":"reduce-component@1.0.1","resolved":"https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz","version":"1.0.1"}},"from":"superagent@~0.15.7","version":"0.15.7"},"superagent-proxy":{"dependencies":{"proxy-agent":{"dependencies":{"http-proxy-agent":{"dependencies":{"agent-base":{"from":"agent-base@~1.0.1","version":"1.0.1"},"debug":{"from":"debug@~0.7.0","version":"0.7.4"},"extend":{"from":"extend@~1.2.0","version":"1.2.1"}},"from":"http-proxy-agent@0","resolved":"https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-0.2.4.tgz","version":"0.2.4"},"https-proxy-agent":{"dependencies":{"agent-base":{"from":"agent-base@~1.0.1","version":"1.0.1"},"debug":{"from":"debug@~0.7.0","version":"0.7.4"},"extend":{"from":"extend@~1.2.0","version":"1.2.1"}},"from":"https-proxy-agent@0","resolved":"https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-0.3.3.tgz","version":"0.3.3"},"lru-cache":{"from":"lru-cache@~2.3.1","version":"2.3.1"},"socks-proxy-agent":{"dependencies":{"agent-base":{"from":"agent-base@~1.0.1","version":"1.0.1"},"extend":{"from":"extend@~1.2.0","version":"1.2.1"},"rainbowsocks":{"dependencies":{"debug":{"from":"debug@~0.7.2","version":"0.7.4"}},"from":"rainbowsocks@~0.1.0","version":"0.1.1"}},"from":"socks-proxy-agent@0","version":"0.1.0"}},"from":"proxy-agent@~0.0.2","version":"0.0.2"}},"from":"superagent-proxy@~0.2.0","version":"0.2.0"}},"from":"w3cjs@~0.1.22","version":"0.1.22"}},"from":"grunt-html-validation@~0.1.13","version":"0.1.13"},"grunt-jekyll":{"dependencies":{"tmp":{"from":"tmp@0.0.21","resolved":"https://registry.npmjs.org/tmp/-/tmp-0.0.21.tgz","version":"0.0.21"}},"from":"grunt-jekyll@~0.4.1","version":"0.4.1"},"grunt-jscs-checker":{"dependencies":{"hooker":{"from":"hooker@~0.2.3","resolved":"https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz","version":"0.2.3"},"jscs":{"dependencies":{"colors":{"from":"colors@0.6.0-1","resolved":"https://registry.npmjs.org/colors/-/colors-0.6.0-1.tgz","version":"0.6.0-1"},"commander":{"dependencies":{"keypress":{"from":"keypress@0.1.x","version":"0.1.0"}},"from":"commander@1.2.0","resolved":"https://registry.npmjs.org/commander/-/commander-1.2.0.tgz","version":"1.2.0"},"esprima":{"from":"esprima@1.0.3","resolved":"https://registry.npmjs.org/esprima/-/esprima-1.0.3.tgz","version":"1.0.3"},"glob":{"dependencies":{"inherits":{"from":"inherits@2","version":"2.0.1"}},"from":"glob@3.2.7","resolved":"https://registry.npmjs.org/glob/-/glob-3.2.7.tgz","version":"3.2.7"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@0.2.12","resolved":"https://registry.npmjs.org/minimatch/-/minimatch-0.2.12.tgz","version":"0.2.12"},"vow":{"from":"vow@0.3.9","resolved":"https://registry.npmjs.org/vow/-/vow-0.3.9.tgz","version":"0.3.9"},"vow-fs":{"dependencies":{"node-uuid":{"from":"node-uuid@1.4.0","resolved":"https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.0.tgz","version":"1.4.0"},"vow-queue":{"from":"vow-queue@0.0.2","resolved":"https://registry.npmjs.org/vow-queue/-/vow-queue-0.0.2.tgz","version":"0.0.2"}},"from":"vow-fs@0.2.3","resolved":"https://registry.npmjs.org/vow-fs/-/vow-fs-0.2.3.tgz","version":"0.2.3"},"xmlbuilder":{"dependencies":{"underscore":{"from":"underscore@>=1.5.x","version":"1.5.2"}},"from":"xmlbuilder@1.1.2","resolved":"https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-1.1.2.tgz","version":"1.1.2"}},"from":"jscs@~1.2.0","resolved":"https://registry.npmjs.org/jscs/-/jscs-1.2.3.tgz","version":"1.2.3"},"lodash.assign":{"dependencies":{"lodash._basecreatecallback":{"dependencies":{"lodash._setbinddata":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"},"lodash.noop":{"from":"lodash.noop@~2.4.1","version":"2.4.1"}},"from":"lodash._setbinddata@~2.4.1","version":"2.4.1"},"lodash.bind":{"dependencies":{"lodash._createwrapper":{"dependencies":{"lodash._basebind":{"dependencies":{"lodash._basecreate":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"},"lodash.noop":{"from":"lodash.noop@~2.4.1","version":"2.4.1"}},"from":"lodash._basecreate@~2.4.1","version":"2.4.1"},"lodash.isobject":{"from":"lodash.isobject@~2.4.1","version":"2.4.1"}},"from":"lodash._basebind@~2.4.1","version":"2.4.1"},"lodash._basecreatewrapper":{"dependencies":{"lodash._basecreate":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"},"lodash.noop":{"from":"lodash.noop@~2.4.1","version":"2.4.1"}},"from":"lodash._basecreate@~2.4.1","version":"2.4.1"},"lodash.isobject":{"from":"lodash.isobject@~2.4.1","version":"2.4.1"}},"from":"lodash._basecreatewrapper@~2.4.1","version":"2.4.1"},"lodash.isfunction":{"from":"lodash.isfunction@~2.4.1","version":"2.4.1"}},"from":"lodash._createwrapper@~2.4.1","version":"2.4.1"},"lodash._slice":{"from":"lodash._slice@~2.4.1","version":"2.4.1"}},"from":"lodash.bind@~2.4.1","version":"2.4.1"},"lodash.identity":{"from":"lodash.identity@~2.4.1","version":"2.4.1"},"lodash.support":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"}},"from":"lodash.support@~2.4.1","version":"2.4.1"}},"from":"lodash._basecreatecallback@~2.4.1","version":"2.4.1"},"lodash._objecttypes":{"from":"lodash._objecttypes@~2.4.1","version":"2.4.1"},"lodash.keys":{"dependencies":{"lodash._isnative":{"from":"lodash._isnative@~2.4.1","version":"2.4.1"},"lodash._shimkeys":{"from":"lodash._shimkeys@~2.4.1","version":"2.4.1"},"lodash.isobject":{"from":"lodash.isobject@~2.4.1","version":"2.4.1"}},"from":"lodash.keys@~2.4.1","version":"2.4.1"}},"from":"lodash.assign@2.4.1","resolved":"https://registry.npmjs.org/lodash.assign/-/lodash.assign-2.4.1.tgz","version":"2.4.1"},"vow":{"from":"vow@0.4.0","resolved":"https://registry.npmjs.org/vow/-/vow-0.4.0.tgz","version":"0.4.0"}},"from":"grunt-jscs-checker@~0.3.0","resolved":"https://registry.npmjs.org/grunt-jscs-checker/-/grunt-jscs-checker-0.3.2.tgz","version":"0.3.2"},"grunt-saucelabs":{"dependencies":{"colors":{"from":"colors@~0.6.0","version":"0.6.2"},"request":{"dependencies":{"aws-sign":{"from":"aws-sign@~0.3.0","version":"0.3.0"},"cookie-jar":{"from":"cookie-jar@~0.3.0","version":"0.3.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"async":{"from":"async@~0.2.9","version":"0.2.9"},"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@~0.1.0","version":"0.1.2"},"hawk":{"dependencies":{"boom":{"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.9.x","version":"0.9.1"},"sntp":{"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~1.0.0","version":"1.0.0"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.10.0","version":"0.10.0"},"json-stringify-safe":{"from":"json-stringify-safe@~5.0.0","version":"5.0.0"},"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@~2.27.0","version":"2.27.0"},"sauce-tunnel":{"dependencies":{"request":{"dependencies":{"aws-sign":{"from":"aws-sign@~0.3.0","version":"0.3.0"},"cookie-jar":{"from":"cookie-jar@~0.3.0","version":"0.3.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"async":{"from":"async@~0.2.7","version":"0.2.9"},"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@0.0.8","resolved":"https://registry.npmjs.org/form-data/-/form-data-0.0.8.tgz","version":"0.0.8"},"hawk":{"dependencies":{"boom":{"dependencies":{"hoek":{"from":"hoek@0.9.x","version":"0.9.1"}},"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.8.x","version":"0.8.5"},"sntp":{"dependencies":{"hoek":{"from":"hoek@0.9.x","version":"0.9.1"}},"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~0.13.0","version":"0.13.1"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.9.11","version":"0.9.11"},"json-stringify-safe":{"from":"json-stringify-safe@~4.0.0","version":"4.0.0"},"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@~2.21.0","version":"2.21.0"}},"from":"sauce-tunnel@~1.0.0","version":"1.0.2"},"saucelabs":{"from":"saucelabs@~0.1.0","version":"0.1.1"},"wd":{"dependencies":{"archiver":{"dependencies":{"iconv-lite":{"from":"iconv-lite@~0.2.11","version":"0.2.11"},"readable-stream":{"from":"readable-stream@~1.0.2","version":"1.0.24"}},"from":"archiver@~0.4.6","version":"0.4.10"},"async":{"from":"async@0.2.x","version":"0.2.9"},"lodash":{"from":"lodash@~1.3.1","version":"1.3.1"},"q":{"from":"q@0.9.x","version":"0.9.7"},"request":{"dependencies":{"aws-sign":{"from":"aws-sign@~0.3.0","version":"0.3.0"},"cookie-jar":{"from":"cookie-jar@~0.3.0","version":"0.3.0"},"forever-agent":{"from":"forever-agent@~0.5.0","version":"0.5.0"},"form-data":{"dependencies":{"combined-stream":{"dependencies":{"delayed-stream":{"from":"delayed-stream@0.0.5","resolved":"https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz","version":"0.0.5"}},"from":"combined-stream@~0.0.4","version":"0.0.4"}},"from":"form-data@0.0.8","resolved":"https://registry.npmjs.org/form-data/-/form-data-0.0.8.tgz","version":"0.0.8"},"hawk":{"dependencies":{"boom":{"dependencies":{"hoek":{"from":"hoek@0.9.x","version":"0.9.1"}},"from":"boom@0.4.x","version":"0.4.2"},"cryptiles":{"from":"cryptiles@0.2.x","version":"0.2.2"},"hoek":{"from":"hoek@0.8.x","version":"0.8.5"},"sntp":{"dependencies":{"hoek":{"from":"hoek@0.9.x","version":"0.9.1"}},"from":"sntp@0.2.x","version":"0.2.4"}},"from":"hawk@~0.13.0","version":"0.13.1"},"http-signature":{"dependencies":{"asn1":{"from":"asn1@0.1.11","resolved":"https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz","version":"0.1.11"},"assert-plus":{"from":"assert-plus@0.1.2","resolved":"https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz","version":"0.1.2"},"ctype":{"from":"ctype@0.5.2","resolved":"https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz","version":"0.5.2"}},"from":"http-signature@~0.9.11","version":"0.9.11"},"json-stringify-safe":{"from":"json-stringify-safe@~4.0.0","version":"4.0.0"},"mime":{"from":"mime@~1.2.9","version":"1.2.11"},"node-uuid":{"from":"node-uuid@~1.4.0","version":"1.4.1"},"oauth-sign":{"from":"oauth-sign@~0.3.0","version":"0.3.0"},"qs":{"from":"qs@~0.6.0","resolved":"https://registry.npmjs.org/qs/-/qs-0.6.6.tgz","version":"0.6.6"},"tunnel-agent":{"from":"tunnel-agent@~0.3.0","version":"0.3.0"}},"from":"request@~2.21.0","version":"2.21.0"},"vargs":{"from":"vargs@~0.1.0","version":"0.1.0"}},"from":"wd@~0.1.0","version":"0.1.5"}},"from":"grunt-saucelabs@~4.1.2","version":"4.1.2"},"grunt-sed":{"dependencies":{"replace":{"dependencies":{"colors":{"from":"colors@0.5.x","version":"0.5.1"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.9","version":"0.2.14"},"nomnom":{"dependencies":{"underscore":{"from":"underscore@~1.4.4","version":"1.4.4"}},"from":"nomnom@1.6.x","version":"1.6.2"}},"from":"replace@~0.2.4","version":"0.2.7"}},"from":"grunt-sed@~0.1.1","version":"0.1.1"},"load-grunt-tasks":{"dependencies":{"findup-sync":{"dependencies":{"glob":{"dependencies":{"graceful-fs":{"from":"graceful-fs@~1.2.0","version":"1.2.3"},"inherits":{"from":"inherits@1","version":"1.0.0"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.11","version":"0.2.14"}},"from":"glob@~3.1.21","version":"3.1.21"},"lodash":{"from":"lodash@~1.0.1","version":"1.0.1"}},"from":"findup-sync@~0.1.2","version":"0.1.2"},"globule":{"dependencies":{"glob":{"dependencies":{"inherits":{"from":"inherits@2","version":"2.0.1"}},"from":"glob@~3.2.7","version":"3.2.8"},"lodash":{"from":"lodash@~2.4.1","resolved":"https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz","version":"2.4.1"},"minimatch":{"dependencies":{"lru-cache":{"from":"lru-cache@2","version":"2.5.0"},"sigmund":{"from":"sigmund@~1.0.0","version":"1.0.0"}},"from":"minimatch@~0.2.11","version":"0.2.14"}},"from":"globule@~0.2.0","resolved":"https://registry.npmjs.org/globule/-/globule-0.2.0.tgz","version":"0.2.0"}},"from":"load-grunt-tasks@~0.3.0","resolved":"https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-0.3.0.tgz","version":"0.3.0"},"markdown":{"dependencies":{"nopt":{"dependencies":{"abbrev":{"from":"abbrev@1","version":"1.0.4"}},"from":"nopt@~2.1.1","version":"2.1.2"}},"from":"markdown@~0.5.0","version":"0.5.0"}},"name":"bootstrap","version":"3.1.0"} \ No newline at end of file diff --git a/dist/bower_components/bootstrap/test-infra/requirements.txt b/dist/bower_components/bootstrap/test-infra/requirements.txt deleted file mode 100644 index 95fbf1a3b..000000000 --- a/dist/bower_components/bootstrap/test-infra/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -boto==2.20.0 diff --git a/dist/bower_components/bootstrap/test-infra/s3_cache.py b/dist/bower_components/bootstrap/test-infra/s3_cache.py deleted file mode 100644 index adc466e00..000000000 --- a/dist/bower_components/bootstrap/test-infra/s3_cache.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python2.7 -from __future__ import absolute_import, unicode_literals, print_function, division - -from sys import argv -from os import environ, stat, remove as _delete_file -from os.path import isfile, dirname, basename, abspath -from hashlib import sha256 -from subprocess import check_call as run - -from boto.s3.connection import S3Connection -from boto.s3.key import Key -from boto.exception import S3ResponseError - - -NEED_TO_UPLOAD_MARKER = '.need-to-upload' -BYTES_PER_MB = 1024 * 1024 -try: - BUCKET_NAME = environ['TWBS_S3_BUCKET'] -except KeyError: - raise SystemExit("TWBS_S3_BUCKET environment variable not set!") - - -def _sha256_of_file(filename): - hasher = sha256() - with open(filename, 'rb') as input_file: - hasher.update(input_file.read()) - file_hash = hasher.hexdigest() - print('sha256({}) = {}'.format(filename, file_hash)) - return file_hash - - -def _delete_file_quietly(filename): - try: - _delete_file(filename) - except (OSError, IOError): - pass - - -def _tarball_size(directory): - kib = stat(_tarball_filename_for(directory)).st_size // BYTES_PER_MB - return "{} MiB".format(kib) - - -def _tarball_filename_for(directory): - return abspath('./{}.tar.gz'.format(basename(directory))) - - -def _create_tarball(directory): - print("Creating tarball of {}...".format(directory)) - run(['tar', '-czf', _tarball_filename_for(directory), '-C', dirname(directory), basename(directory)]) - - -def _extract_tarball(directory): - print("Extracting tarball of {}...".format(directory)) - run(['tar', '-xzf', _tarball_filename_for(directory), '-C', dirname(directory)]) - - -def download(directory): - _delete_file_quietly(NEED_TO_UPLOAD_MARKER) - try: - print("Downloading {} tarball from S3...".format(friendly_name)) - key.get_contents_to_filename(_tarball_filename_for(directory)) - except S3ResponseError as err: - open(NEED_TO_UPLOAD_MARKER, 'a').close() - print(err) - raise SystemExit("Cached {} download failed!".format(friendly_name)) - print("Downloaded {}.".format(_tarball_size(directory))) - _extract_tarball(directory) - print("{} successfully installed from cache.".format(friendly_name)) - - -def upload(directory): - _create_tarball(directory) - print("Uploading {} tarball to S3... ({})".format(friendly_name, _tarball_size(directory))) - key.set_contents_from_filename(_tarball_filename_for(directory)) - print("{} cache successfully updated.".format(friendly_name)) - _delete_file_quietly(NEED_TO_UPLOAD_MARKER) - - -if __name__ == '__main__': - # Uses environment variables: - # AWS_ACCESS_KEY_ID -- AWS Access Key ID - # AWS_SECRET_ACCESS_KEY -- AWS Secret Access Key - argv.pop(0) - if len(argv) != 4: - raise SystemExit("USAGE: s3_cache.py ") - mode, friendly_name, dependencies_file, directory = argv - - conn = S3Connection() - bucket = conn.lookup(BUCKET_NAME) - if bucket is None: - raise SystemExit("Could not access bucket!") - - dependencies_file_hash = _sha256_of_file(dependencies_file) - - key = Key(bucket, dependencies_file_hash) - key.storage_class = 'REDUCED_REDUNDANCY' - - if mode == 'download': - download(directory) - elif mode == 'upload': - if isfile(NEED_TO_UPLOAD_MARKER): # FIXME - upload(directory) - else: - print("No need to upload anything.") - else: - raise SystemExit("Unrecognized mode {!r}".format(mode)) diff --git a/dist/bower_components/bootstrap/test-infra/sauce_browsers.yml b/dist/bower_components/bootstrap/test-infra/sauce_browsers.yml deleted file mode 100644 index 9ec9c4cb1..000000000 --- a/dist/bower_components/bootstrap/test-infra/sauce_browsers.yml +++ /dev/null @@ -1,83 +0,0 @@ -[ - # Docs: https://saucelabs.com/docs/platforms/webdriver - - { - browserName: "safari", - platform: "OS X 10.9" - }, - { - browserName: "chrome", - platform: "OS X 10.9", - version: "31" - }, - { - browserName: "firefox", - platform: "OS X 10.9" - }, - - # Mac Opera not currently supported by Sauce Labs - - { - browserName: "internet explorer", - version: "11", - platform: "Windows 8.1" - }, - { - browserName: "internet explorer", - version: "10", - platform: "Windows 8" - }, - # { - # browserName: "internet explorer", - # version: "9", - # platform: "Windows 7" - # }, - # { - # browserName: "internet explorer", - # version: "8", - # platform: "Windows 7" - # }, - - # { # Unofficial - # browserName: "internet explorer", - # version: "7", - # platform: "Windows XP" - # }, - - { - browserName: "chrome", - platform: "Windows 8.1" - }, - { - browserName: "firefox", - platform: "Windows 8.1" - }, - - # Win Opera 15+ not currently supported by Sauce Labs - - { - browserName: "iphone", - platform: "OS X 10.9", - version: "7" - }, - - # iOS Chrome not currently supported by Sauce Labs - - # Linux (unofficial) - { - browserName: "chrome", - platform: "Linux" - }, - { - browserName: "firefox", - platform: "Linux" - } - - # Android Chrome not currently supported by Sauce Labs - - # { # Android Browser (super-unofficial) - # browserName: "android", - # version: "4.0", - # platform: "Linux" - # } -] diff --git a/dist/bower_components/bootstrap/test-infra/shrinkwrap.js b/dist/bower_components/bootstrap/test-infra/shrinkwrap.js deleted file mode 100644 index 7a0328d41..000000000 --- a/dist/bower_components/bootstrap/test-infra/shrinkwrap.js +++ /dev/null @@ -1,24 +0,0 @@ -/* jshint node: true */ - -/* -This Grunt task updates the npm-shrinkwrap.canonical.json file that's used as the key for Bootstrap's npm packages cache. -This task should be run and the updated file should be committed whenever Bootstrap's dependencies change. -*/ - -var canonicallyJsonStringify = require('canonical-json'); -var NON_CANONICAL_FILE = 'npm-shrinkwrap.json'; -var DEST_FILE = 'test-infra/npm-shrinkwrap.canonical.json'; - - -function updateShrinkwrap(grunt) { - // Assumption: Non-canonical shrinkwrap already generated by prerequisite Grunt task - var shrinkwrapData = grunt.file.readJSON(NON_CANONICAL_FILE); - grunt.log.writeln('Deleting ' + NON_CANONICAL_FILE.cyan + '...'); - grunt.file.delete(NON_CANONICAL_FILE); - // Output as Canonical JSON in correct location - grunt.file.write(DEST_FILE, canonicallyJsonStringify(shrinkwrapData)); - grunt.log.writeln('File ' + DEST_FILE.cyan + ' updated.'); -} - - -module.exports = updateShrinkwrap; diff --git a/dist/bower_components/bootstrap/test-infra/uncached-npm-install.sh b/dist/bower_components/bootstrap/test-infra/uncached-npm-install.sh deleted file mode 100644 index 1c5624986..000000000 --- a/dist/bower_components/bootstrap/test-infra/uncached-npm-install.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -cp test-infra/npm-shrinkwrap.canonical.json npm-shrinkwrap.json -npm install -rm npm-shrinkwrap.json diff --git a/dist/bower_components/es5-shim/.bower.json b/dist/bower_components/es5-shim/.bower.json deleted file mode 100644 index 146a31e82..000000000 --- a/dist/bower_components/es5-shim/.bower.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "es5-shim", - "homepage": "https://github.com/es-shims/es5-shim", - "version": "2.1.0", - "_release": "2.1.0", - "_resolution": { - "type": "version", - "tag": "v2.1.0", - "commit": "07da727ff7db2a3a25d6bc25d13e374b3bbc99c2" - }, - "_source": "git://github.com/es-shims/es5-shim.git", - "_target": "~2.1.0", - "_originalSource": "es5-shim" -} \ No newline at end of file diff --git a/dist/bower_components/es5-shim/.gitignore b/dist/bower_components/es5-shim/.gitignore deleted file mode 100644 index fd4f2b066..000000000 --- a/dist/bower_components/es5-shim/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -.DS_Store diff --git a/dist/bower_components/es5-shim/CHANGES b/dist/bower_components/es5-shim/CHANGES deleted file mode 100644 index f6f4f046e..000000000 --- a/dist/bower_components/es5-shim/CHANGES +++ /dev/null @@ -1,93 +0,0 @@ - -2.0.0 - - Separate reliable shims from dubious shims (shams). - -1.2.10 - - Group-effort Style Cleanup - - Took a stab at fixing Object.defineProperty on IE8 without - bad side-effects. (@hax) - - Object.isExtensible no longer fakes it. (@xavierm) - - Date.prototype.toISOString no longer deals with partial - ISO dates, per spec (@kitcambridge) - - More (mostly from @bryanforbes) - -1.2.9 - - Corrections to toISOString by @kitcambridge - - Fixed three bugs in array methods revealed by Jasmine tests. - - Cleaned up Function.prototype.bind with more fixes and tests from - @bryanforbes. - -1.2.8 - - Actually fixed problems with Function.prototype.bind, and regressions - from 1.2.7 (@bryanforbes, @jdalton #36) - -1.2.7 - REGRESSED - - Fixed problems with Function.prototype.bind when called as a constructor. - (@jdalton #36) - -1.2.6 - - Revised Date.parse to match ES 5.1 (kitcambridge) - -1.2.5 - - Fixed a bug for padding it Date..toISOString (tadfisher issue #33) - -1.2.4 - - Fixed a descriptor bug in Object.defineProperty (raynos) - -1.2.3 - - Cleaned up RequireJS and - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dist/bower_components/es5-shim/tests/index.min.html b/dist/bower_components/es5-shim/tests/index.min.html deleted file mode 100644 index 65e590a32..000000000 --- a/dist/bower_components/es5-shim/tests/index.min.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - Jasmine Spec Runner - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dist/bower_components/es5-shim/tests/lib/jasmine-html.js b/dist/bower_components/es5-shim/tests/lib/jasmine-html.js deleted file mode 100644 index 73834010f..000000000 --- a/dist/bower_components/es5-shim/tests/lib/jasmine-html.js +++ /dev/null @@ -1,190 +0,0 @@ -jasmine.TrivialReporter = function(doc) { - this.document = doc || document; - this.suiteDivs = {}; - this.logRunningSpecs = false; -}; - -jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { - var el = document.createElement(type); - - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(document.createTextNode(child)); - } else { - if (child) { el.appendChild(child); } - } - } - - for (var attr in attrs) { - if (attr == "className") { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } - } - - return el; -}; - -jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { - var showPassed, showSkipped; - - this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' }, - this.createDom('div', { className: 'banner' }, - this.createDom('div', { className: 'logo' }, - this.createDom('span', { className: 'title' }, "Jasmine"), - this.createDom('span', { className: 'version' }, runner.env.versionString())), - this.createDom('div', { className: 'options' }, - "Show ", - showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), - showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") - ) - ), - - this.runnerDiv = this.createDom('div', { className: 'runner running' }, - this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), - this.runnerMessageSpan = this.createDom('span', {}, "Running..."), - this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) - ); - - this.document.body.appendChild(this.outerDiv); - - var suites = runner.suites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - var suiteDiv = this.createDom('div', { className: 'suite' }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), - this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); - this.suiteDivs[suite.id] = suiteDiv; - var parentDiv = this.outerDiv; - if (suite.parentSuite) { - parentDiv = this.suiteDivs[suite.parentSuite.id]; - } - parentDiv.appendChild(suiteDiv); - } - - this.startedAt = new Date(); - - var self = this; - showPassed.onclick = function(evt) { - if (showPassed.checked) { - self.outerDiv.className += ' show-passed'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); - } - }; - - showSkipped.onclick = function(evt) { - if (showSkipped.checked) { - self.outerDiv.className += ' show-skipped'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); - } - }; -}; - -jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { - var results = runner.results(); - var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; - this.runnerDiv.setAttribute("class", className); - //do it twice for IE - this.runnerDiv.setAttribute("className", className); - var specs = runner.specs(); - var specCount = 0; - for (var i = 0; i < specs.length; i++) { - if (this.specFilter(specs[i])) { - specCount++; - } - } - var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); - message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; - this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); - - this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); -}; - -jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { - var results = suite.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.totalCount === 0) { // todo: change this to check results.skipped - status = 'skipped'; - } - this.suiteDivs[suite.id].className += " " + status; -}; - -jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { - if (this.logRunningSpecs) { - this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); - } -}; - -jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { - var results = spec.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.skipped) { - status = 'skipped'; - } - var specDiv = this.createDom('div', { className: 'spec ' + status }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), - this.createDom('a', { - className: 'description', - href: '?spec=' + encodeURIComponent(spec.getFullName()), - title: spec.getFullName() - }, spec.description)); - - - var resultItems = results.getItems(); - var messagesDiv = this.createDom('div', { className: 'messages' }); - for (var i = 0; i < resultItems.length; i++) { - var result = resultItems[i]; - - if (result.type == 'log') { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); - } else if (result.type == 'expect' && result.passed && !result.passed()) { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); - - if (result.trace.stack) { - messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); - } - } - } - - if (messagesDiv.childNodes.length > 0) { - specDiv.appendChild(messagesDiv); - } - - this.suiteDivs[spec.suite.id].appendChild(specDiv); -}; - -jasmine.TrivialReporter.prototype.log = function() { - var console = jasmine.getGlobal().console; - if (console && console.log) { - if (console.log.apply) { - console.log.apply(console, arguments); - } else { - console.log(arguments); // ie fix: console.log.apply doesn't exist on ie - } - } -}; - -jasmine.TrivialReporter.prototype.getLocation = function() { - return this.document.location; -}; - -jasmine.TrivialReporter.prototype.specFilter = function(spec) { - var paramMap = {}; - var params = this.getLocation().search.substring(1).split('&'); - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - } - - if (!paramMap.spec) { - return true; - } - return spec.getFullName().indexOf(paramMap.spec) === 0; -}; diff --git a/dist/bower_components/es5-shim/tests/lib/jasmine.css b/dist/bower_components/es5-shim/tests/lib/jasmine.css deleted file mode 100644 index 6583fe7c6..000000000 --- a/dist/bower_components/es5-shim/tests/lib/jasmine.css +++ /dev/null @@ -1,166 +0,0 @@ -body { - font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; -} - - -.jasmine_reporter a:visited, .jasmine_reporter a { - color: #303; -} - -.jasmine_reporter a:hover, .jasmine_reporter a:active { - color: blue; -} - -.run_spec { - float:right; - padding-right: 5px; - font-size: .8em; - text-decoration: none; -} - -.jasmine_reporter { - margin: 0 5px; -} - -.banner { - color: #303; - background-color: #fef; - padding: 5px; -} - -.logo { - float: left; - font-size: 1.1em; - padding-left: 5px; -} - -.logo .version { - font-size: .6em; - padding-left: 1em; -} - -.runner.running { - background-color: yellow; -} - - -.options { - text-align: right; - font-size: .8em; -} - - - - -.suite { - border: 1px outset gray; - margin: 5px 0; - padding-left: 1em; -} - -.suite .suite { - margin: 5px; -} - -.suite.passed { - background-color: #dfd; -} - -.suite.failed { - background-color: #fdd; -} - -.spec { - margin: 5px; - padding-left: 1em; - clear: both; -} - -.spec.failed, .spec.passed, .spec.skipped { - padding-bottom: 5px; - border: 1px solid gray; -} - -.spec.failed { - background-color: #fbb; - border-color: red; -} - -.spec.passed { - background-color: #bfb; - border-color: green; -} - -.spec.skipped { - background-color: #bbb; -} - -.messages { - border-left: 1px dashed gray; - padding-left: 1em; - padding-right: 1em; -} - -.passed { - background-color: #cfc; - display: none; -} - -.failed { - background-color: #fbb; -} - -.skipped { - color: #777; - background-color: #eee; - display: none; -} - - -/*.resultMessage {*/ - /*white-space: pre;*/ -/*}*/ - -.resultMessage span.result { - display: block; - line-height: 2em; - color: black; -} - -.resultMessage .mismatch { - color: black; -} - -.stackTrace { - white-space: pre; - font-size: .8em; - margin-left: 10px; - max-height: 5em; - overflow: auto; - border: 1px inset red; - padding: 1em; - background: #eef; -} - -.finished-at { - padding-left: 1em; - font-size: .6em; -} - -.show-passed .passed, -.show-skipped .skipped { - display: block; -} - - -#jasmine_content { - position:fixed; - right: 100%; -} - -.runner { - border: 1px solid gray; - display: block; - margin: 5px 0; - padding: 2px 0 2px 10px; -} diff --git a/dist/bower_components/es5-shim/tests/lib/jasmine.js b/dist/bower_components/es5-shim/tests/lib/jasmine.js deleted file mode 100644 index 70d7d25e1..000000000 --- a/dist/bower_components/es5-shim/tests/lib/jasmine.js +++ /dev/null @@ -1,2477 +0,0 @@ -var isCommonJS = typeof window == "undefined"; - -/** - * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. - * - * @namespace - */ -var jasmine = {}; -if (isCommonJS) exports.jasmine = jasmine; -/** - * @private - */ -jasmine.unimplementedMethod_ = function() { - throw new Error("unimplemented method"); -}; - -/** - * Use jasmine.undefined instead of undefined, since undefined is just - * a plain old variable and may be redefined by somebody else. - * - * @private - */ -jasmine.undefined = jasmine.___undefined___; - -/** - * Show diagnostic messages in the console if set to true - * - */ -jasmine.VERBOSE = false; - -/** - * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. - * - */ -jasmine.DEFAULT_UPDATE_INTERVAL = 250; - -/** - * Default timeout interval in milliseconds for waitsFor() blocks. - */ -jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; - -jasmine.getGlobal = function() { - function getGlobal() { - return this; - } - - return getGlobal(); -}; - -/** - * Allows for bound functions to be compared. Internal use only. - * - * @ignore - * @private - * @param base {Object} bound 'this' for the function - * @param name {Function} function to find - */ -jasmine.bindOriginal_ = function(base, name) { - var original = base[name]; - if (original.apply) { - return function() { - return original.apply(base, arguments); - }; - } else { - // IE support - return jasmine.getGlobal()[name]; - } -}; - -jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); -jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); -jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); -jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); - -jasmine.MessageResult = function(values) { - this.type = 'log'; - this.values = values; - this.trace = new Error(); // todo: test better -}; - -jasmine.MessageResult.prototype.toString = function() { - var text = ""; - for (var i = 0; i < this.values.length; i++) { - if (i > 0) text += " "; - if (jasmine.isString_(this.values[i])) { - text += this.values[i]; - } else { - text += jasmine.pp(this.values[i]); - } - } - return text; -}; - -jasmine.ExpectationResult = function(params) { - this.type = 'expect'; - this.matcherName = params.matcherName; - this.passed_ = params.passed; - this.expected = params.expected; - this.actual = params.actual; - this.message = this.passed_ ? 'Passed.' : params.message; - - var trace = (params.trace || new Error(this.message)); - this.trace = this.passed_ ? '' : trace; -}; - -jasmine.ExpectationResult.prototype.toString = function () { - return this.message; -}; - -jasmine.ExpectationResult.prototype.passed = function () { - return this.passed_; -}; - -/** - * Getter for the Jasmine environment. Ensures one gets created - */ -jasmine.getEnv = function() { - var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); - return env; -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isArray_ = function(value) { - return jasmine.isA_("Array", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isString_ = function(value) { - return jasmine.isA_("String", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isNumber_ = function(value) { - return jasmine.isA_("Number", value); -}; - -/** - * @ignore - * @private - * @param {String} typeName - * @param value - * @returns {Boolean} - */ -jasmine.isA_ = function(typeName, value) { - return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; -}; - -/** - * Pretty printer for expecations. Takes any object and turns it into a human-readable string. - * - * @param value {Object} an object to be outputted - * @returns {String} - */ -jasmine.pp = function(value) { - var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); - stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; -}; - -/** - * Returns true if the object is a DOM Node. - * - * @param {Object} obj object to check - * @returns {Boolean} - */ -jasmine.isDomNode = function(obj) { - return obj.nodeType > 0; -}; - -/** - * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. - * - * @example - * // don't care about which function is passed in, as long as it's a function - * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); - * - * @param {Class} clazz - * @returns matchable object of the type clazz - */ -jasmine.any = function(clazz) { - return new jasmine.Matchers.Any(clazz); -}; - -/** - * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. - * - * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine - * expectation syntax. Spies can be checked if they were called or not and what the calling params were. - * - * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). - * - * Spies are torn down at the end of every spec. - * - * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. - * - * @example - * // a stub - * var myStub = jasmine.createSpy('myStub'); // can be used anywhere - * - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // actual foo.not will not be called, execution stops - * spyOn(foo, 'not'); - - // foo.not spied upon, execution will continue to implementation - * spyOn(foo, 'not').andCallThrough(); - * - * // fake example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // foo.not(val) will return val - * spyOn(foo, 'not').andCallFake(function(value) {return value;}); - * - * // mock example - * foo.not(7 == 7); - * expect(foo.not).toHaveBeenCalled(); - * expect(foo.not).toHaveBeenCalledWith(true); - * - * @constructor - * @see spyOn, jasmine.createSpy, jasmine.createSpyObj - * @param {String} name - */ -jasmine.Spy = function(name) { - /** - * The name of the spy, if provided. - */ - this.identity = name || 'unknown'; - /** - * Is this Object a spy? - */ - this.isSpy = true; - /** - * The actual function this spy stubs. - */ - this.plan = function() { - }; - /** - * Tracking of the most recent call to the spy. - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy.mostRecentCall.args = [1, 2]; - */ - this.mostRecentCall = {}; - - /** - * Holds arguments for each call to the spy, indexed by call count - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy(7, 8); - * mySpy.mostRecentCall.args = [7, 8]; - * mySpy.argsForCall[0] = [1, 2]; - * mySpy.argsForCall[1] = [7, 8]; - */ - this.argsForCall = []; - this.calls = []; -}; - -/** - * Tells a spy to call through to the actual implemenatation. - * - * @example - * var foo = { - * bar: function() { // do some stuff } - * } - * - * // defining a spy on an existing property: foo.bar - * spyOn(foo, 'bar').andCallThrough(); - */ -jasmine.Spy.prototype.andCallThrough = function() { - this.plan = this.originalValue; - return this; -}; - -/** - * For setting the return value of a spy. - * - * @example - * // defining a spy from scratch: foo() returns 'baz' - * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); - * - * // defining a spy on an existing property: foo.bar() returns 'baz' - * spyOn(foo, 'bar').andReturn('baz'); - * - * @param {Object} value - */ -jasmine.Spy.prototype.andReturn = function(value) { - this.plan = function() { - return value; - }; - return this; -}; - -/** - * For throwing an exception when a spy is called. - * - * @example - * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' - * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); - * - * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' - * spyOn(foo, 'bar').andThrow('baz'); - * - * @param {String} exceptionMsg - */ -jasmine.Spy.prototype.andThrow = function(exceptionMsg) { - this.plan = function() { - throw exceptionMsg; - }; - return this; -}; - -/** - * Calls an alternate implementation when a spy is called. - * - * @example - * var baz = function() { - * // do some stuff, return something - * } - * // defining a spy from scratch: foo() calls the function baz - * var foo = jasmine.createSpy('spy on foo').andCall(baz); - * - * // defining a spy on an existing property: foo.bar() calls an anonymnous function - * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); - * - * @param {Function} fakeFunc - */ -jasmine.Spy.prototype.andCallFake = function(fakeFunc) { - this.plan = fakeFunc; - return this; -}; - -/** - * Resets all of a spy's the tracking variables so that it can be used again. - * - * @example - * spyOn(foo, 'bar'); - * - * foo.bar(); - * - * expect(foo.bar.callCount).toEqual(1); - * - * foo.bar.reset(); - * - * expect(foo.bar.callCount).toEqual(0); - */ -jasmine.Spy.prototype.reset = function() { - this.wasCalled = false; - this.callCount = 0; - this.argsForCall = []; - this.calls = []; - this.mostRecentCall = {}; -}; - -jasmine.createSpy = function(name) { - - var spyObj = function() { - spyObj.wasCalled = true; - spyObj.callCount++; - var args = jasmine.util.argsToArray(arguments); - spyObj.mostRecentCall.object = this; - spyObj.mostRecentCall.args = args; - spyObj.argsForCall.push(args); - spyObj.calls.push({object: this, args: args}); - return spyObj.plan.apply(this, arguments); - }; - - var spy = new jasmine.Spy(name); - - for (var prop in spy) { - spyObj[prop] = spy[prop]; - } - - spyObj.reset(); - - return spyObj; -}; - -/** - * Determines whether an object is a spy. - * - * @param {jasmine.Spy|Object} putativeSpy - * @returns {Boolean} - */ -jasmine.isSpy = function(putativeSpy) { - return putativeSpy && putativeSpy.isSpy; -}; - -/** - * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something - * large in one call. - * - * @param {String} baseName name of spy class - * @param {Array} methodNames array of names of methods to make spies - */ -jasmine.createSpyObj = function(baseName, methodNames) { - if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { - throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); - } - var obj = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); - } - return obj; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the current spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.log = function() { - var spec = jasmine.getEnv().currentSpec; - spec.log.apply(spec, arguments); -}; - -/** - * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. - * - * @example - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops - * - * @see jasmine.createSpy - * @param obj - * @param methodName - * @returns a Jasmine spy that can be chained with all spy methods - */ -var spyOn = function(obj, methodName) { - return jasmine.getEnv().currentSpec.spyOn(obj, methodName); -}; -if (isCommonJS) exports.spyOn = spyOn; - -/** - * Creates a Jasmine spec that will be added to the current suite. - * - * // TODO: pending tests - * - * @example - * it('should be true', function() { - * expect(true).toEqual(true); - * }); - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var it = function(desc, func) { - return jasmine.getEnv().it(desc, func); -}; -if (isCommonJS) exports.it = it; - -/** - * Creates a disabled Jasmine spec. - * - * A convenience method that allows existing specs to be disabled temporarily during development. - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var xit = function(desc, func) { - return jasmine.getEnv().xit(desc, func); -}; -if (isCommonJS) exports.xit = xit; - -/** - * Starts a chain for a Jasmine expectation. - * - * It is passed an Object that is the actual value and should chain to one of the many - * jasmine.Matchers functions. - * - * @param {Object} actual Actual value to test against and expected value - */ -var expect = function(actual) { - return jasmine.getEnv().currentSpec.expect(actual); -}; -if (isCommonJS) exports.expect = expect; - -/** - * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. - * - * @param {Function} func Function that defines part of a jasmine spec. - */ -var runs = function(func) { - jasmine.getEnv().currentSpec.runs(func); -}; -if (isCommonJS) exports.runs = runs; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -var waits = function(timeout) { - jasmine.getEnv().currentSpec.waits(timeout); -}; -if (isCommonJS) exports.waits = waits; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); -}; -if (isCommonJS) exports.waitsFor = waitsFor; - -/** - * A function that is called before each spec in a suite. - * - * Used for spec setup, including validating assumptions. - * - * @param {Function} beforeEachFunction - */ -var beforeEach = function(beforeEachFunction) { - jasmine.getEnv().beforeEach(beforeEachFunction); -}; -if (isCommonJS) exports.beforeEach = beforeEach; - -/** - * A function that is called after each spec in a suite. - * - * Used for restoring any state that is hijacked during spec execution. - * - * @param {Function} afterEachFunction - */ -var afterEach = function(afterEachFunction) { - jasmine.getEnv().afterEach(afterEachFunction); -}; -if (isCommonJS) exports.afterEach = afterEach; - -/** - * Defines a suite of specifications. - * - * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared - * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization - * of setup in some tests. - * - * @example - * // TODO: a simple suite - * - * // TODO: a simple suite with a nested describe block - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var describe = function(description, specDefinitions) { - return jasmine.getEnv().describe(description, specDefinitions); -}; -if (isCommonJS) exports.describe = describe; - -/** - * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var xdescribe = function(description, specDefinitions) { - return jasmine.getEnv().xdescribe(description, specDefinitions); -}; -if (isCommonJS) exports.xdescribe = xdescribe; - - -// Provide the XMLHttpRequest class for IE 5.x-6.x: -jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { - function tryIt(f) { - try { - return f(); - } catch(e) { - } - return null; - } - - var xhr = tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP.6.0"); - }) || - tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP.3.0"); - }) || - tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP"); - }) || - tryIt(function() { - return new ActiveXObject("Microsoft.XMLHTTP"); - }); - - if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); - - return xhr; -} : XMLHttpRequest; -/** - * @namespace - */ -jasmine.util = {}; - -/** - * Declare that a child class inherit it's prototype from the parent class. - * - * @private - * @param {Function} childClass - * @param {Function} parentClass - */ -jasmine.util.inherit = function(childClass, parentClass) { - /** - * @private - */ - var subclass = function() { - }; - subclass.prototype = parentClass.prototype; - childClass.prototype = new subclass(); -}; - -jasmine.util.formatException = function(e) { - var lineNumber; - if (e.line) { - lineNumber = e.line; - } - else if (e.lineNumber) { - lineNumber = e.lineNumber; - } - - var file; - - if (e.sourceURL) { - file = e.sourceURL; - } - else if (e.fileName) { - file = e.fileName; - } - - var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); - - if (file && lineNumber) { - message += ' in ' + file + ' (line ' + lineNumber + ')'; - } - - return message; -}; - -jasmine.util.htmlEscape = function(str) { - if (!str) return str; - return str.replace(/&/g, '&') - .replace(//g, '>'); -}; - -jasmine.util.argsToArray = function(args) { - var arrayOfArgs = []; - for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); - return arrayOfArgs; -}; - -jasmine.util.extend = function(destination, source) { - for (var property in source) destination[property] = source[property]; - return destination; -}; - -/** - * Environment for Jasmine - * - * @constructor - */ -jasmine.Env = function() { - this.currentSpec = null; - this.currentSuite = null; - this.currentRunner_ = new jasmine.Runner(this); - - this.reporter = new jasmine.MultiReporter(); - - this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; - this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; - this.lastUpdate = 0; - this.specFilter = function() { - return true; - }; - - this.nextSpecId_ = 0; - this.nextSuiteId_ = 0; - this.equalityTesters_ = []; - - // wrap matchers - this.matchersClass = function() { - jasmine.Matchers.apply(this, arguments); - }; - jasmine.util.inherit(this.matchersClass, jasmine.Matchers); - - jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); -}; - - -jasmine.Env.prototype.setTimeout = jasmine.setTimeout; -jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; -jasmine.Env.prototype.setInterval = jasmine.setInterval; -jasmine.Env.prototype.clearInterval = jasmine.clearInterval; - -/** - * @returns an object containing jasmine version build info, if set. - */ -jasmine.Env.prototype.version = function () { - if (jasmine.version_) { - return jasmine.version_; - } else { - throw new Error('Version not set'); - } -}; - -/** - * @returns string containing jasmine version build info, if set. - */ -jasmine.Env.prototype.versionString = function() { - if (!jasmine.version_) { - return "version unknown"; - } - - var version = this.version(); - var versionString = version.major + "." + version.minor + "." + version.build; - if (version.release_candidate) { - versionString += ".rc" + version.release_candidate - } - versionString += " revision " + version.revision; - return versionString; -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSpecId = function () { - return this.nextSpecId_++; -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSuiteId = function () { - return this.nextSuiteId_++; -}; - -/** - * Register a reporter to receive status updates from Jasmine. - * @param {jasmine.Reporter} reporter An object which will receive status updates. - */ -jasmine.Env.prototype.addReporter = function(reporter) { - this.reporter.addReporter(reporter); -}; - -jasmine.Env.prototype.execute = function() { - this.currentRunner_.execute(); -}; - -jasmine.Env.prototype.describe = function(description, specDefinitions) { - var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); - - var parentSuite = this.currentSuite; - if (parentSuite) { - parentSuite.add(suite); - } else { - this.currentRunner_.add(suite); - } - - this.currentSuite = suite; - - var declarationError = null; - try { - specDefinitions.call(suite); - } catch(e) { - declarationError = e; - } - - if (declarationError) { - this.it("encountered a declaration exception", function() { - throw declarationError; - }); - } - - this.currentSuite = parentSuite; - - return suite; -}; - -jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { - if (this.currentSuite) { - this.currentSuite.beforeEach(beforeEachFunction); - } else { - this.currentRunner_.beforeEach(beforeEachFunction); - } -}; - -jasmine.Env.prototype.currentRunner = function () { - return this.currentRunner_; -}; - -jasmine.Env.prototype.afterEach = function(afterEachFunction) { - if (this.currentSuite) { - this.currentSuite.afterEach(afterEachFunction); - } else { - this.currentRunner_.afterEach(afterEachFunction); - } - -}; - -jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { - return { - execute: function() { - } - }; -}; - -jasmine.Env.prototype.it = function(description, func) { - var spec = new jasmine.Spec(this, this.currentSuite, description); - this.currentSuite.add(spec); - this.currentSpec = spec; - - if (func) { - spec.runs(func); - } - - return spec; -}; - -jasmine.Env.prototype.xit = function(desc, func) { - return { - id: this.nextSpecId(), - runs: function() { - } - }; -}; - -jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { - if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { - return true; - } - - a.__Jasmine_been_here_before__ = b; - b.__Jasmine_been_here_before__ = a; - - var hasKey = function(obj, keyName) { - return obj !== null && obj[keyName] !== jasmine.undefined; - }; - - for (var property in b) { - if (!hasKey(a, property) && hasKey(b, property)) { - mismatchKeys.push("expected has key '" + property + "', but missing from actual."); - } - } - for (property in a) { - if (!hasKey(b, property) && hasKey(a, property)) { - mismatchKeys.push("expected missing key '" + property + "', but present in actual."); - } - } - for (property in b) { - if (property == '__Jasmine_been_here_before__') continue; - if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { - mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); - } - } - - if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { - mismatchValues.push("arrays were not the same length"); - } - - delete a.__Jasmine_been_here_before__; - delete b.__Jasmine_been_here_before__; - return (mismatchKeys.length === 0 && mismatchValues.length === 0); -}; - -jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { - mismatchKeys = mismatchKeys || []; - mismatchValues = mismatchValues || []; - - for (var i = 0; i < this.equalityTesters_.length; i++) { - var equalityTester = this.equalityTesters_[i]; - var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); - if (result !== jasmine.undefined) return result; - } - - if (a === b) return true; - - if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { - return (a == jasmine.undefined && b == jasmine.undefined); - } - - if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { - return a === b; - } - - if (a instanceof Date && b instanceof Date) { - return a.getTime() == b.getTime(); - } - - if (a instanceof jasmine.Matchers.Any) { - return a.matches(b); - } - - if (b instanceof jasmine.Matchers.Any) { - return b.matches(a); - } - - if (jasmine.isString_(a) && jasmine.isString_(b)) { - return (a == b); - } - - if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { - return (a == b); - } - - if (typeof a === "object" && typeof b === "object") { - return this.compareObjects_(a, b, mismatchKeys, mismatchValues); - } - - //Straight check - return (a === b); -}; - -jasmine.Env.prototype.contains_ = function(haystack, needle) { - if (jasmine.isArray_(haystack)) { - for (var i = 0; i < haystack.length; i++) { - if (this.equals_(haystack[i], needle)) return true; - } - return false; - } - return haystack.indexOf(needle) >= 0; -}; - -jasmine.Env.prototype.addEqualityTester = function(equalityTester) { - this.equalityTesters_.push(equalityTester); -}; -/** No-op base class for Jasmine reporters. - * - * @constructor - */ -jasmine.Reporter = function() { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerResults = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecStarting = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecResults = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.log = function(str) { -}; - -/** - * Blocks are functions with executable code that make up a spec. - * - * @constructor - * @param {jasmine.Env} env - * @param {Function} func - * @param {jasmine.Spec} spec - */ -jasmine.Block = function(env, func, spec) { - this.env = env; - this.func = func; - this.spec = spec; -}; - -jasmine.Block.prototype.execute = function(onComplete) { - try { - this.func.apply(this.spec); - } catch (e) { - this.spec.fail(e); - } - onComplete(); -}; -/** JavaScript API reporter. - * - * @constructor - */ -jasmine.JsApiReporter = function() { - this.started = false; - this.finished = false; - this.suites_ = []; - this.results_ = {}; -}; - -jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { - this.started = true; - var suites = runner.topLevelSuites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - this.suites_.push(this.summarize_(suite)); - } -}; - -jasmine.JsApiReporter.prototype.suites = function() { - return this.suites_; -}; - -jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { - var isSuite = suiteOrSpec instanceof jasmine.Suite; - var summary = { - id: suiteOrSpec.id, - name: suiteOrSpec.description, - type: isSuite ? 'suite' : 'spec', - children: [] - }; - - if (isSuite) { - var children = suiteOrSpec.children(); - for (var i = 0; i < children.length; i++) { - summary.children.push(this.summarize_(children[i])); - } - } - return summary; -}; - -jasmine.JsApiReporter.prototype.results = function() { - return this.results_; -}; - -jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { - return this.results_[specId]; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { - this.finished = true; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { - this.results_[spec.id] = { - messages: spec.results().getItems(), - result: spec.results().failedCount > 0 ? "failed" : "passed" - }; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.log = function(str) { -}; - -jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ - var results = {}; - for (var i = 0; i < specIds.length; i++) { - var specId = specIds[i]; - results[specId] = this.summarizeResult_(this.results_[specId]); - } - return results; -}; - -jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ - var summaryMessages = []; - var messagesLength = result.messages.length; - for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { - var resultMessage = result.messages[messageIndex]; - summaryMessages.push({ - text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, - passed: resultMessage.passed ? resultMessage.passed() : true, - type: resultMessage.type, - message: resultMessage.message, - trace: { - stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined - } - }); - } - - return { - result : result.result, - messages : summaryMessages - }; -}; - -/** - * @constructor - * @param {jasmine.Env} env - * @param actual - * @param {jasmine.Spec} spec - */ -jasmine.Matchers = function(env, actual, spec, opt_isNot) { - this.env = env; - this.actual = actual; - this.spec = spec; - this.isNot = opt_isNot || false; - this.reportWasCalled_ = false; -}; - -// todo: @deprecated as of Jasmine 0.11, remove soon [xw] -jasmine.Matchers.pp = function(str) { - throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); -}; - -// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] -jasmine.Matchers.prototype.report = function(result, failing_message, details) { - throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); -}; - -jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { - for (var methodName in prototype) { - if (methodName == 'report') continue; - var orig = prototype[methodName]; - matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); - } -}; - -jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { - return function() { - var matcherArgs = jasmine.util.argsToArray(arguments); - var result = matcherFunction.apply(this, arguments); - - if (this.isNot) { - result = !result; - } - - if (this.reportWasCalled_) return result; - - var message; - if (!result) { - if (this.message) { - message = this.message.apply(this, arguments); - if (jasmine.isArray_(message)) { - message = message[this.isNot ? 1 : 0]; - } - } else { - var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; - if (matcherArgs.length > 0) { - for (var i = 0; i < matcherArgs.length; i++) { - if (i > 0) message += ","; - message += " " + jasmine.pp(matcherArgs[i]); - } - } - message += "."; - } - } - var expectationResult = new jasmine.ExpectationResult({ - matcherName: matcherName, - passed: result, - expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], - actual: this.actual, - message: message - }); - this.spec.addMatcherResult(expectationResult); - return jasmine.undefined; - }; -}; - - - - -/** - * toBe: compares the actual to the expected using === - * @param expected - */ -jasmine.Matchers.prototype.toBe = function(expected) { - return this.actual === expected; -}; - -/** - * toNotBe: compares the actual to the expected using !== - * @param expected - * @deprecated as of 1.0. Use not.toBe() instead. - */ -jasmine.Matchers.prototype.toNotBe = function(expected) { - return this.actual !== expected; -}; - -/** - * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. - * - * @param expected - */ -jasmine.Matchers.prototype.toEqual = function(expected) { - return this.env.equals_(this.actual, expected); -}; - -/** - * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual - * @param expected - * @deprecated as of 1.0. Use not.toNotEqual() instead. - */ -jasmine.Matchers.prototype.toNotEqual = function(expected) { - return !this.env.equals_(this.actual, expected); -}; - -/** - * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes - * a pattern or a String. - * - * @param expected - */ -jasmine.Matchers.prototype.toMatch = function(expected) { - return new RegExp(expected).test(this.actual); -}; - -/** - * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch - * @param expected - * @deprecated as of 1.0. Use not.toMatch() instead. - */ -jasmine.Matchers.prototype.toNotMatch = function(expected) { - return !(new RegExp(expected).test(this.actual)); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeDefined = function() { - return (this.actual !== jasmine.undefined); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeUndefined = function() { - return (this.actual === jasmine.undefined); -}; - -/** - * Matcher that compares the actual to null. - */ -jasmine.Matchers.prototype.toBeNull = function() { - return (this.actual === null); -}; - -/** - * Matcher that boolean not-nots the actual. - */ -jasmine.Matchers.prototype.toBeTruthy = function() { - return !!this.actual; -}; - - -/** - * Matcher that boolean nots the actual. - */ -jasmine.Matchers.prototype.toBeFalsy = function() { - return !this.actual; -}; - - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called. - */ -jasmine.Matchers.prototype.toHaveBeenCalled = function() { - if (arguments.length > 0) { - throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to have been called.", - "Expected spy " + this.actual.identity + " not to have been called." - ]; - }; - - return this.actual.wasCalled; -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ -jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was not called. - * - * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead - */ -jasmine.Matchers.prototype.wasNotCalled = function() { - if (arguments.length > 0) { - throw new Error('wasNotCalled does not take arguments'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to not have been called.", - "Expected spy " + this.actual.identity + " to have been called." - ]; - }; - - return !this.actual.wasCalled; -}; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. - * - * @example - * - */ -jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - this.message = function() { - if (this.actual.callCount === 0) { - // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] - return [ - "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", - "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was." - ]; - } else { - return [ - "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), - "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) - ]; - } - }; - - return this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; - -/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasNotCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", - "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" - ]; - }; - - return !this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** - * Matcher that checks that the expected item is an element in the actual Array. - * - * @param {Object} expected - */ -jasmine.Matchers.prototype.toContain = function(expected) { - return this.env.contains_(this.actual, expected); -}; - -/** - * Matcher that checks that the expected item is NOT an element in the actual Array. - * - * @param {Object} expected - * @deprecated as of 1.0. Use not.toNotContain() instead. - */ -jasmine.Matchers.prototype.toNotContain = function(expected) { - return !this.env.contains_(this.actual, expected); -}; - -jasmine.Matchers.prototype.toBeLessThan = function(expected) { - return this.actual < expected; -}; - -jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { - return this.actual > expected; -}; - -/** - * Matcher that checks that the expected item is equal to the actual item - * up to a given level of decimal precision (default 2). - * - * @param {Number} expected - * @param {Number} precision - */ -jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { - if (!(precision === 0)) { - precision = precision || 2; - } - var multiplier = Math.pow(10, precision); - var actual = Math.round(this.actual * multiplier); - expected = Math.round(expected * multiplier); - return expected == actual; -}; - -/** - * Matcher that checks that the expected exception was thrown by the actual. - * - * @param {String} expected - */ -jasmine.Matchers.prototype.toThrow = function(expected) { - var result = false; - var exception; - if (typeof this.actual != 'function') { - throw new Error('Actual is not a function'); - } - try { - this.actual(); - } catch (e) { - exception = e; - } - if (exception) { - result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); - } - - var not = this.isNot ? "not " : ""; - - this.message = function() { - if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { - return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); - } else { - return "Expected function to throw an exception."; - } - }; - - return result; -}; - -jasmine.Matchers.Any = function(expectedClass) { - this.expectedClass = expectedClass; -}; - -jasmine.Matchers.Any.prototype.matches = function(other) { - if (this.expectedClass == String) { - return typeof other == 'string' || other instanceof String; - } - - if (this.expectedClass == Number) { - return typeof other == 'number' || other instanceof Number; - } - - if (this.expectedClass == Function) { - return typeof other == 'function' || other instanceof Function; - } - - if (this.expectedClass == Object) { - return typeof other == 'object'; - } - - return other instanceof this.expectedClass; -}; - -jasmine.Matchers.Any.prototype.toString = function() { - return ''; -}; - -/** - * @constructor - */ -jasmine.MultiReporter = function() { - this.subReporters_ = []; -}; -jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); - -jasmine.MultiReporter.prototype.addReporter = function(reporter) { - this.subReporters_.push(reporter); -}; - -(function() { - var functionNames = [ - "reportRunnerStarting", - "reportRunnerResults", - "reportSuiteResults", - "reportSpecStarting", - "reportSpecResults", - "log" - ]; - for (var i = 0; i < functionNames.length; i++) { - var functionName = functionNames[i]; - jasmine.MultiReporter.prototype[functionName] = (function(functionName) { - return function() { - for (var j = 0; j < this.subReporters_.length; j++) { - var subReporter = this.subReporters_[j]; - if (subReporter[functionName]) { - subReporter[functionName].apply(subReporter, arguments); - } - } - }; - })(functionName); - } -})(); -/** - * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults - * - * @constructor - */ -jasmine.NestedResults = function() { - /** - * The total count of results - */ - this.totalCount = 0; - /** - * Number of passed results - */ - this.passedCount = 0; - /** - * Number of failed results - */ - this.failedCount = 0; - /** - * Was this suite/spec skipped? - */ - this.skipped = false; - /** - * @ignore - */ - this.items_ = []; -}; - -/** - * Roll up the result counts. - * - * @param result - */ -jasmine.NestedResults.prototype.rollupCounts = function(result) { - this.totalCount += result.totalCount; - this.passedCount += result.passedCount; - this.failedCount += result.failedCount; -}; - -/** - * Adds a log message. - * @param values Array of message parts which will be concatenated later. - */ -jasmine.NestedResults.prototype.log = function(values) { - this.items_.push(new jasmine.MessageResult(values)); -}; - -/** - * Getter for the results: message & results. - */ -jasmine.NestedResults.prototype.getItems = function() { - return this.items_; -}; - -/** - * Adds a result, tracking counts (total, passed, & failed) - * @param {jasmine.ExpectationResult|jasmine.NestedResults} result - */ -jasmine.NestedResults.prototype.addResult = function(result) { - if (result.type != 'log') { - if (result.items_) { - this.rollupCounts(result); - } else { - this.totalCount++; - if (result.passed()) { - this.passedCount++; - } else { - this.failedCount++; - } - } - } - this.items_.push(result); -}; - -/** - * @returns {Boolean} True if everything below passed - */ -jasmine.NestedResults.prototype.passed = function() { - return this.passedCount === this.totalCount; -}; -/** - * Base class for pretty printing for expectation results. - */ -jasmine.PrettyPrinter = function() { - this.ppNestLevel_ = 0; -}; - -/** - * Formats a value in a nice, human-readable string. - * - * @param value - */ -jasmine.PrettyPrinter.prototype.format = function(value) { - if (this.ppNestLevel_ > 40) { - throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); - } - - this.ppNestLevel_++; - try { - if (value === jasmine.undefined) { - this.emitScalar('undefined'); - } else if (value === null) { - this.emitScalar('null'); - } else if (value === jasmine.getGlobal()) { - this.emitScalar(''); - } else if (value instanceof jasmine.Matchers.Any) { - this.emitScalar(value.toString()); - } else if (typeof value === 'string') { - this.emitString(value); - } else if (jasmine.isSpy(value)) { - this.emitScalar("spy on " + value.identity); - } else if (value instanceof RegExp) { - this.emitScalar(value.toString()); - } else if (typeof value === 'function') { - this.emitScalar('Function'); - } else if (typeof value.nodeType === 'number') { - this.emitScalar('HTMLNode'); - } else if (value instanceof Date) { - this.emitScalar('Date(' + value + ')'); - } else if (value.__Jasmine_been_here_before__) { - this.emitScalar(''); - } else if (jasmine.isArray_(value) || typeof value == 'object') { - value.__Jasmine_been_here_before__ = true; - if (jasmine.isArray_(value)) { - this.emitArray(value); - } else { - this.emitObject(value); - } - delete value.__Jasmine_been_here_before__; - } else { - this.emitScalar(value.toString()); - } - } finally { - this.ppNestLevel_--; - } -}; - -jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { - for (var property in obj) { - if (property == '__Jasmine_been_here_before__') continue; - fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && - obj.__lookupGetter__(property) !== null) : false); - } -}; - -jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; - -jasmine.StringPrettyPrinter = function() { - jasmine.PrettyPrinter.call(this); - - this.string = ''; -}; -jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); - -jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { - this.append(value); -}; - -jasmine.StringPrettyPrinter.prototype.emitString = function(value) { - this.append("'" + value + "'"); -}; - -jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { - this.append('[ '); - for (var i = 0; i < array.length; i++) { - if (i > 0) { - this.append(', '); - } - this.format(array[i]); - } - this.append(' ]'); -}; - -jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { - var self = this; - this.append('{ '); - var first = true; - - this.iterateObject(obj, function(property, isGetter) { - if (first) { - first = false; - } else { - self.append(', '); - } - - self.append(property); - self.append(' : '); - if (isGetter) { - self.append(''); - } else { - self.format(obj[property]); - } - }); - - this.append(' }'); -}; - -jasmine.StringPrettyPrinter.prototype.append = function(value) { - this.string += value; -}; -jasmine.Queue = function(env) { - this.env = env; - this.blocks = []; - this.running = false; - this.index = 0; - this.offset = 0; - this.abort = false; -}; - -jasmine.Queue.prototype.addBefore = function(block) { - this.blocks.unshift(block); -}; - -jasmine.Queue.prototype.add = function(block) { - this.blocks.push(block); -}; - -jasmine.Queue.prototype.insertNext = function(block) { - this.blocks.splice((this.index + this.offset + 1), 0, block); - this.offset++; -}; - -jasmine.Queue.prototype.start = function(onComplete) { - this.running = true; - this.onComplete = onComplete; - this.next_(); -}; - -jasmine.Queue.prototype.isRunning = function() { - return this.running; -}; - -jasmine.Queue.LOOP_DONT_RECURSE = true; - -jasmine.Queue.prototype.next_ = function() { - var self = this; - var goAgain = true; - - while (goAgain) { - goAgain = false; - - if (self.index < self.blocks.length && !this.abort) { - var calledSynchronously = true; - var completedSynchronously = false; - - var onComplete = function () { - if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { - completedSynchronously = true; - return; - } - - if (self.blocks[self.index].abort) { - self.abort = true; - } - - self.offset = 0; - self.index++; - - var now = new Date().getTime(); - if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { - self.env.lastUpdate = now; - self.env.setTimeout(function() { - self.next_(); - }, 0); - } else { - if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { - goAgain = true; - } else { - self.next_(); - } - } - }; - self.blocks[self.index].execute(onComplete); - - calledSynchronously = false; - if (completedSynchronously) { - onComplete(); - } - - } else { - self.running = false; - if (self.onComplete) { - self.onComplete(); - } - } - } -}; - -jasmine.Queue.prototype.results = function() { - var results = new jasmine.NestedResults(); - for (var i = 0; i < this.blocks.length; i++) { - if (this.blocks[i].results) { - results.addResult(this.blocks[i].results()); - } - } - return results; -}; - - -/** - * Runner - * - * @constructor - * @param {jasmine.Env} env - */ -jasmine.Runner = function(env) { - var self = this; - self.env = env; - self.queue = new jasmine.Queue(env); - self.before_ = []; - self.after_ = []; - self.suites_ = []; -}; - -jasmine.Runner.prototype.execute = function() { - var self = this; - if (self.env.reporter.reportRunnerStarting) { - self.env.reporter.reportRunnerStarting(this); - } - self.queue.start(function () { - self.finishCallback(); - }); -}; - -jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.splice(0,0,beforeEachFunction); -}; - -jasmine.Runner.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.splice(0,0,afterEachFunction); -}; - - -jasmine.Runner.prototype.finishCallback = function() { - this.env.reporter.reportRunnerResults(this); -}; - -jasmine.Runner.prototype.addSuite = function(suite) { - this.suites_.push(suite); -}; - -jasmine.Runner.prototype.add = function(block) { - if (block instanceof jasmine.Suite) { - this.addSuite(block); - } - this.queue.add(block); -}; - -jasmine.Runner.prototype.specs = function () { - var suites = this.suites(); - var specs = []; - for (var i = 0; i < suites.length; i++) { - specs = specs.concat(suites[i].specs()); - } - return specs; -}; - -jasmine.Runner.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Runner.prototype.topLevelSuites = function() { - var topLevelSuites = []; - for (var i = 0; i < this.suites_.length; i++) { - if (!this.suites_[i].parentSuite) { - topLevelSuites.push(this.suites_[i]); - } - } - return topLevelSuites; -}; - -jasmine.Runner.prototype.results = function() { - return this.queue.results(); -}; -/** - * Internal representation of a Jasmine specification, or test. - * - * @constructor - * @param {jasmine.Env} env - * @param {jasmine.Suite} suite - * @param {String} description - */ -jasmine.Spec = function(env, suite, description) { - if (!env) { - throw new Error('jasmine.Env() required'); - } - if (!suite) { - throw new Error('jasmine.Suite() required'); - } - var spec = this; - spec.id = env.nextSpecId ? env.nextSpecId() : null; - spec.env = env; - spec.suite = suite; - spec.description = description; - spec.queue = new jasmine.Queue(env); - - spec.afterCallbacks = []; - spec.spies_ = []; - - spec.results_ = new jasmine.NestedResults(); - spec.results_.description = description; - spec.matchersClass = null; -}; - -jasmine.Spec.prototype.getFullName = function() { - return this.suite.getFullName() + ' ' + this.description + '.'; -}; - - -jasmine.Spec.prototype.results = function() { - return this.results_; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.Spec.prototype.log = function() { - return this.results_.log(arguments); -}; - -jasmine.Spec.prototype.runs = function (func) { - var block = new jasmine.Block(this.env, func, this); - this.addToQueue(block); - return this; -}; - -jasmine.Spec.prototype.addToQueue = function (block) { - if (this.queue.isRunning()) { - this.queue.insertNext(block); - } else { - this.queue.add(block); - } -}; - -/** - * @param {jasmine.ExpectationResult} result - */ -jasmine.Spec.prototype.addMatcherResult = function(result) { - this.results_.addResult(result); -}; - -jasmine.Spec.prototype.expect = function(actual) { - var positive = new (this.getMatchersClass_())(this.env, actual, this); - positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); - return positive; -}; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -jasmine.Spec.prototype.waits = function(timeout) { - var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); - this.addToQueue(waitsFunc); - return this; -}; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - var latchFunction_ = null; - var optional_timeoutMessage_ = null; - var optional_timeout_ = null; - - for (var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - switch (typeof arg) { - case 'function': - latchFunction_ = arg; - break; - case 'string': - optional_timeoutMessage_ = arg; - break; - case 'number': - optional_timeout_ = arg; - break; - } - } - - var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); - this.addToQueue(waitsForFunc); - return this; -}; - -jasmine.Spec.prototype.fail = function (e) { - var expectationResult = new jasmine.ExpectationResult({ - passed: false, - message: e ? jasmine.util.formatException(e) : 'Exception', - trace: { stack: e.stack } - }); - this.results_.addResult(expectationResult); -}; - -jasmine.Spec.prototype.getMatchersClass_ = function() { - return this.matchersClass || this.env.matchersClass; -}; - -jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { - var parent = this.getMatchersClass_(); - var newMatchersClass = function() { - parent.apply(this, arguments); - }; - jasmine.util.inherit(newMatchersClass, parent); - jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); - this.matchersClass = newMatchersClass; -}; - -jasmine.Spec.prototype.finishCallback = function() { - this.env.reporter.reportSpecResults(this); -}; - -jasmine.Spec.prototype.finish = function(onComplete) { - this.removeAllSpies(); - this.finishCallback(); - if (onComplete) { - onComplete(); - } -}; - -jasmine.Spec.prototype.after = function(doAfter) { - if (this.queue.isRunning()) { - this.queue.add(new jasmine.Block(this.env, doAfter, this)); - } else { - this.afterCallbacks.unshift(doAfter); - } -}; - -jasmine.Spec.prototype.execute = function(onComplete) { - var spec = this; - if (!spec.env.specFilter(spec)) { - spec.results_.skipped = true; - spec.finish(onComplete); - return; - } - - this.env.reporter.reportSpecStarting(this); - - spec.env.currentSpec = spec; - - spec.addBeforesAndAftersToQueue(); - - spec.queue.start(function () { - spec.finish(onComplete); - }); -}; - -jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { - var runner = this.env.currentRunner(); - var i; - - for (var suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); - } - } - for (i = 0; i < runner.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); - } - for (i = 0; i < this.afterCallbacks.length; i++) { - this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); - } - for (suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, suite.after_[i], this)); - } - } - for (i = 0; i < runner.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); - } -}; - -jasmine.Spec.prototype.explodes = function() { - throw 'explodes function should not have been called'; -}; - -jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { - if (obj == jasmine.undefined) { - throw "spyOn could not find an object to spy upon for " + methodName + "()"; - } - - if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { - throw methodName + '() method does not exist'; - } - - if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { - throw new Error(methodName + ' has already been spied upon'); - } - - var spyObj = jasmine.createSpy(methodName); - - this.spies_.push(spyObj); - spyObj.baseObj = obj; - spyObj.methodName = methodName; - spyObj.originalValue = obj[methodName]; - - obj[methodName] = spyObj; - - return spyObj; -}; - -jasmine.Spec.prototype.removeAllSpies = function() { - for (var i = 0; i < this.spies_.length; i++) { - var spy = this.spies_[i]; - spy.baseObj[spy.methodName] = spy.originalValue; - } - this.spies_ = []; -}; - -/** - * Internal representation of a Jasmine suite. - * - * @constructor - * @param {jasmine.Env} env - * @param {String} description - * @param {Function} specDefinitions - * @param {jasmine.Suite} parentSuite - */ -jasmine.Suite = function(env, description, specDefinitions, parentSuite) { - var self = this; - self.id = env.nextSuiteId ? env.nextSuiteId() : null; - self.description = description; - self.queue = new jasmine.Queue(env); - self.parentSuite = parentSuite; - self.env = env; - self.before_ = []; - self.after_ = []; - self.children_ = []; - self.suites_ = []; - self.specs_ = []; -}; - -jasmine.Suite.prototype.getFullName = function() { - var fullName = this.description; - for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { - fullName = parentSuite.description + ' ' + fullName; - } - return fullName; -}; - -jasmine.Suite.prototype.finish = function(onComplete) { - this.env.reporter.reportSuiteResults(this); - this.finished = true; - if (typeof(onComplete) == 'function') { - onComplete(); - } -}; - -jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.unshift(beforeEachFunction); -}; - -jasmine.Suite.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.unshift(afterEachFunction); -}; - -jasmine.Suite.prototype.results = function() { - return this.queue.results(); -}; - -jasmine.Suite.prototype.add = function(suiteOrSpec) { - this.children_.push(suiteOrSpec); - if (suiteOrSpec instanceof jasmine.Suite) { - this.suites_.push(suiteOrSpec); - this.env.currentRunner().addSuite(suiteOrSpec); - } else { - this.specs_.push(suiteOrSpec); - } - this.queue.add(suiteOrSpec); -}; - -jasmine.Suite.prototype.specs = function() { - return this.specs_; -}; - -jasmine.Suite.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Suite.prototype.children = function() { - return this.children_; -}; - -jasmine.Suite.prototype.execute = function(onComplete) { - var self = this; - this.queue.start(function () { - self.finish(onComplete); - }); -}; -jasmine.WaitsBlock = function(env, timeout, spec) { - this.timeout = timeout; - jasmine.Block.call(this, env, null, spec); -}; - -jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); - -jasmine.WaitsBlock.prototype.execute = function (onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); - } - this.env.setTimeout(function () { - onComplete(); - }, this.timeout); -}; -/** - * A block which waits for some condition to become true, with timeout. - * - * @constructor - * @extends jasmine.Block - * @param {jasmine.Env} env The Jasmine environment. - * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. - * @param {Function} latchFunction A function which returns true when the desired condition has been met. - * @param {String} message The message to display if the desired condition hasn't been met within the given time period. - * @param {jasmine.Spec} spec The Jasmine spec. - */ -jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { - this.timeout = timeout || env.defaultTimeoutInterval; - this.latchFunction = latchFunction; - this.message = message; - this.totalTimeSpentWaitingForLatch = 0; - jasmine.Block.call(this, env, null, spec); -}; -jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); - -jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; - -jasmine.WaitsForBlock.prototype.execute = function(onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); - } - var latchFunctionResult; - try { - latchFunctionResult = this.latchFunction.apply(this.spec); - } catch (e) { - this.spec.fail(e); - onComplete(); - return; - } - - if (latchFunctionResult) { - onComplete(); - } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { - var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); - this.spec.fail({ - name: 'timeout', - message: message - }); - - this.abort = true; - onComplete(); - } else { - this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; - var self = this; - this.env.setTimeout(function() { - self.execute(onComplete); - }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); - } -}; -// Mock setTimeout, clearTimeout -// Contributed by Pivotal Computer Systems, www.pivotalsf.com - -jasmine.FakeTimer = function() { - this.reset(); - - var self = this; - self.setTimeout = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); - return self.timeoutsMade; - }; - - self.setInterval = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); - return self.timeoutsMade; - }; - - self.clearTimeout = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - - self.clearInterval = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - -}; - -jasmine.FakeTimer.prototype.reset = function() { - this.timeoutsMade = 0; - this.scheduledFunctions = {}; - this.nowMillis = 0; -}; - -jasmine.FakeTimer.prototype.tick = function(millis) { - var oldMillis = this.nowMillis; - var newMillis = oldMillis + millis; - this.runFunctionsWithinRange(oldMillis, newMillis); - this.nowMillis = newMillis; -}; - -jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { - var scheduledFunc; - var funcsToRun = []; - for (var timeoutKey in this.scheduledFunctions) { - scheduledFunc = this.scheduledFunctions[timeoutKey]; - if (scheduledFunc != jasmine.undefined && - scheduledFunc.runAtMillis >= oldMillis && - scheduledFunc.runAtMillis <= nowMillis) { - funcsToRun.push(scheduledFunc); - this.scheduledFunctions[timeoutKey] = jasmine.undefined; - } - } - - if (funcsToRun.length > 0) { - funcsToRun.sort(function(a, b) { - return a.runAtMillis - b.runAtMillis; - }); - for (var i = 0; i < funcsToRun.length; ++i) { - try { - var funcToRun = funcsToRun[i]; - this.nowMillis = funcToRun.runAtMillis; - funcToRun.funcToCall(); - if (funcToRun.recurring) { - this.scheduleFunction(funcToRun.timeoutKey, - funcToRun.funcToCall, - funcToRun.millis, - true); - } - } catch(e) { - } - } - this.runFunctionsWithinRange(oldMillis, nowMillis); - } -}; - -jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { - this.scheduledFunctions[timeoutKey] = { - runAtMillis: this.nowMillis + millis, - funcToCall: funcToCall, - recurring: recurring, - timeoutKey: timeoutKey, - millis: millis - }; -}; - -/** - * @namespace - */ -jasmine.Clock = { - defaultFakeTimer: new jasmine.FakeTimer(), - - reset: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.reset(); - }, - - tick: function(millis) { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.tick(millis); - }, - - runFunctionsWithinRange: function(oldMillis, nowMillis) { - jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); - }, - - scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { - jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); - }, - - useMock: function() { - if (!jasmine.Clock.isInstalled()) { - var spec = jasmine.getEnv().currentSpec; - spec.after(jasmine.Clock.uninstallMock); - - jasmine.Clock.installMock(); - } - }, - - installMock: function() { - jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; - }, - - uninstallMock: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.installed = jasmine.Clock.real; - }, - - real: { - setTimeout: jasmine.getGlobal().setTimeout, - clearTimeout: jasmine.getGlobal().clearTimeout, - setInterval: jasmine.getGlobal().setInterval, - clearInterval: jasmine.getGlobal().clearInterval - }, - - assertInstalled: function() { - if (!jasmine.Clock.isInstalled()) { - throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); - } - }, - - isInstalled: function() { - return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; - }, - - installed: null -}; -jasmine.Clock.installed = jasmine.Clock.real; - -//else for IE support -jasmine.getGlobal().setTimeout = function(funcToCall, millis) { - if (jasmine.Clock.installed.setTimeout.apply) { - return jasmine.Clock.installed.setTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.setTimeout(funcToCall, millis); - } -}; - -jasmine.getGlobal().setInterval = function(funcToCall, millis) { - if (jasmine.Clock.installed.setInterval.apply) { - return jasmine.Clock.installed.setInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.setInterval(funcToCall, millis); - } -}; - -jasmine.getGlobal().clearTimeout = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearTimeout(timeoutKey); - } -}; - -jasmine.getGlobal().clearInterval = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearInterval(timeoutKey); - } -}; - -jasmine.version_= { - "major": 1, - "minor": 1, - "build": 0, - "revision": 1308618948, - "release_candidate": 1 -}; diff --git a/dist/bower_components/es5-shim/tests/lib/jasmine_favicon.png b/dist/bower_components/es5-shim/tests/lib/jasmine_favicon.png deleted file mode 100644 index 218f3b43713598fa5a3e78b57aceb909c33f46df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 905 zcmV;419tq0P)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_0008u zNkl3{fod28|PjmA)7fYg4w8-(2my9xtBGOs}K`n&t1VzxMO^X)M zrW+Ln1udc?q6TP)z5gAjt)P&D!M$+HJK#x<`xnD030zwD?KrxxY!2tlA zGc-58?0D7SsT)7Km=v+tNVNUk`?s@;^OxCF)y6P}_mL;~7;S<@b|MzmKq)m8l@yky zT1~ECpxZw@64!nkI34QLiUsA%i%N>-$&zGYR7WJyi9ERMyS(%kf z7A_r)X>!90&m(FwDQZ>q;+nOa*KR2+E6Fz)QwU=W1Oyo*4>_qlm|~joa|{4_A_3W8 z#FFZzRp-xMIx5a7D_Fj3&#r^TbIY@cND1d0f*^qDIs{!pw!IWGQ_%l4#ASm_D5Vet z0%ek7^)@xPihX_G0&hIc9*14ca=D!8oG}vW?H%~w^F?f_s>zU|fKrNJXJ_d6{v!t( zpEoqMws_yQws>3o?VW8Txq~#->dJG^ELW5irR!s`(_JvD^6;r+ho~eIK@ia8_lH(h zt*-p?CFC1_h2MV=?jP){uW!7WjLjCaO&c1D+tf582!XEaoB#xWAYcN5f$sLtf$koW zQs{{>)ZTq?FC6|J_%n}AWbiFK(Bo-%^-{H`*)E(ucjo-r%SYm)W5f6tN=xz=S646E fNXW#U{x?4WXWJ 3; - }); - expect(arr).toEqual([1,2,3,4,5,6]); - expect(i).toBe(3); - }); - it('should set the right context when given none', function() { - var context; - [1].some(function() {context = this;}); - expect(context).toBe(function() {return this}.call()); - }); - - it('should return false if it runs to the end', function() { - actual = testSubject.some(function() {}); - expect(actual).toBeFalsy(); - }); - it('should return true if it is stopped somewhere', function() { - actual = testSubject.some(function() { return true; }); - expect(actual).toBeTruthy(); - }); - it('should return false if there are no elements', function() { - actual = [].some(function() { return true; }); - expect(actual).toBeFalsy(); - }); - - it('should stop after 3 elements', function() { - testSubject.some(function(obj, index) { - actual[index] = obj; - numberOfRuns += 1; - if(numberOfRuns == 3) { - return true; - } - return false; - }); - expect(actual).toExactlyMatch(expected); - }); - it('should stop after 3 elements using a context', function() { - var o = { a: actual }; - testSubject.some(function(obj, index) { - this.a[index] = obj; - numberOfRuns += 1; - if(numberOfRuns == 3) { - return true; - } - return false; - }, o); - expect(actual).toExactlyMatch(expected); - }); - - it('should stop after 3 elements in an array-like object', function() { - var ts = createArrayLikeFromArray(testSubject); - Array.prototype.some.call(ts, function(obj, index) { - actual[index] = obj; - numberOfRuns += 1; - if(numberOfRuns == 3) { - return true; - } - return false; - }); - expect(actual).toExactlyMatch(expected); - }); - it('should stop after 3 elements in an array-like object using a context', function() { - var ts = createArrayLikeFromArray(testSubject); - var o = { a: actual }; - Array.prototype.some.call(ts, function(obj, index) { - this.a[index] = obj; - numberOfRuns += 1; - if(numberOfRuns == 3) { - return true; - } - return false; - }, o); - expect(actual).toExactlyMatch(expected); - }); - }); - describe('every', function() { - var actual, expected, numberOfRuns; - - beforeEach(function() { - expected = {0:2, 2: undefined, 3:true }; - actual = {}; - numberOfRuns = 0; - }); - - it('should pass the correct values along to the callback', function() { - var callback = jasmine.createSpy('callback'); - var array = ['1']; - array.every(callback); - expect(callback).toHaveBeenCalledWith('1', 0, array); - }); - it('should not affect elements added to the array after it has begun', function() { - var arr = [1,2,3], - i = 0; - arr.every(function(a) { - i++; - arr.push(a+3); - return i <= 3; - }); - expect(arr).toEqual([1,2,3,4,5,6]); - expect(i).toBe(3); - }); - it('should set the right context when given none', function() { - var context; - [1].every(function() {context = this;}); - expect(context).toBe(function() {return this}.call()); - }); - - it('should return true if the array is empty', function() { - actual = [].every(function() { return true; }); - expect(actual).toBeTruthy(); - - actual = [].every(function() { return false; }); - expect(actual).toBeTruthy(); - }); - it('should return true if it runs to the end', function() { - actual = [1,2,3].every(function() { return true; }); - expect(actual).toBeTruthy(); - }); - it('should return false if it is stopped before the end', function() { - actual = [1,2,3].every(function() { return false; }); - expect(actual).toBeFalsy(); - }); - - it('should return after 3 elements', function() { - testSubject.every(function(obj, index) { - actual[index] = obj; - numberOfRuns += 1; - if(numberOfRuns == 3) { - return false; - } - return true; - }); - expect(actual).toExactlyMatch(expected); - }); - it('should stop after 3 elements using a context', function() { - var o = { a: actual }; - testSubject.every(function(obj, index) { - this.a[index] = obj; - numberOfRuns += 1; - if(numberOfRuns == 3) { - return false; - } - return true; - }, o); - expect(actual).toExactlyMatch(expected); - }); - - it('should stop after 3 elements in an array-like object', function() { - var ts = createArrayLikeFromArray(testSubject); - Array.prototype.every.call(ts, function(obj, index) { - actual[index] = obj; - numberOfRuns += 1; - if(numberOfRuns == 3) { - return false; - } - return true; - }); - expect(actual).toExactlyMatch(expected); - }); - it('should stop after 3 elements in an array-like object using a context', function() { - var ts = createArrayLikeFromArray(testSubject); - var o = { a: actual }; - Array.prototype.every.call(ts, function(obj, index) { - this.a[index] = obj; - numberOfRuns += 1; - if(numberOfRuns == 3) { - return false; - } - return true; - }, o); - expect(actual).toExactlyMatch(expected); - }); - }); - - describe('indexOf', function() { - "use strict"; - var actual, expected, testSubject; - - beforeEach(function() { - testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0]; - delete testSubject[1]; - - }); - - it('should find the element', function() { - expected = 4; - actual = testSubject.indexOf('hej'); - expect(actual).toEqual(expected); - }); - it('should not find the element', function() { - expected = -1; - actual = testSubject.indexOf('mus'); - expect(actual).toEqual(expected); - }); - it('should find undefined as well', function() { - expected = -1; - actual = testSubject.indexOf(undefined); - expect(actual).not.toEqual(expected); - }); - it('should skip unset indexes', function() { - expected = 2; - actual = testSubject.indexOf(undefined); - expect(actual).toEqual(expected); - }); - it('should use a strict test', function() { - actual = testSubject.indexOf(null); - expect(actual).toEqual(5); - - actual = testSubject.indexOf('2'); - expect(actual).toEqual(-1); - }); - it('should skip the first if fromIndex is set', function() { - expect(testSubject.indexOf(2, 2)).toEqual(6); - expect(testSubject.indexOf(2, 0)).toEqual(0); - expect(testSubject.indexOf(2, 6)).toEqual(6); - }); - it('should work with negative fromIndex', function() { - expect(testSubject.indexOf(2, -3)).toEqual(6); - expect(testSubject.indexOf(2, -9)).toEqual(0); - }); - it('should work with fromIndex being greater than the length', function() { - expect(testSubject.indexOf(0, 20)).toEqual(-1); - }); - it('should work with fromIndex being negative and greater than the length', function() { - expect(testSubject.indexOf('hej', -20)).toEqual(4); - }); - - describe('Array-like', function ArrayLike() { - var indexOf = Array.prototype.indexOf, - testAL; - beforeEach(function beforeEach() { - testAL = {}; - testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0]; - testSubject.forEach(function (o,i) { - testAL[i] = o; - }); - testAL.length = testSubject.length; - }); - it('should find the element (array-like)', function() { - expected = 4; - actual = indexOf.call(testAL, 'hej'); - expect(actual).toEqual(expected); - }); - it('should not find the element (array-like)', function() { - expected = -1; - actual = indexOf.call(testAL, 'mus'); - expect(actual).toEqual(expected); - }); - it('should find undefined as well (array-like)', function() { - expected = -1; - actual = indexOf.call(testAL, undefined); - expect(actual).not.toEqual(expected); - }); - it('should skip unset indexes (array-like)', function() { - expected = 2; - actual = indexOf.call(testAL, undefined); - expect(actual).toEqual(expected); - }); - it('should use a strict test (array-like)', function() { - actual = Array.prototype.indexOf.call(testAL, null); - expect(actual).toEqual(5); - - actual = Array.prototype.indexOf.call(testAL, '2'); - expect(actual).toEqual(-1); - }); - it('should skip the first if fromIndex is set (array-like)', function() { - expect(indexOf.call(testAL, 2, 2)).toEqual(6); - expect(indexOf.call(testAL, 2, 0)).toEqual(0); - expect(indexOf.call(testAL, 2, 6)).toEqual(6); - }); - it('should work with negative fromIndex (array-like)', function() { - expect(indexOf.call(testAL, 2, -3)).toEqual(6); - expect(indexOf.call(testAL, 2, -9)).toEqual(0); - }); - it('should work with fromIndex being greater than the length (array-like)', function() { - expect(indexOf.call(testAL, 0, 20)).toEqual(-1); - }); - it('should work with fromIndex being negative and greater than the length (array-like)', function() { - expect(indexOf.call(testAL, 'hej', -20)).toEqual(4); - }); - }); - }); - describe('lastIndexOf', function() { - "use strict"; - var actual, expected, testSubject, testAL; - - beforeEach(function() { - testSubject = [2, 3, undefined, true, 'hej', null, 2, 3, false, 0]; - delete testSubject[1]; - delete testSubject[7]; - }); - describe('Array', function() { - it('should find the element', function() { - expected = 4; - actual = testSubject.lastIndexOf('hej'); - expect(actual).toEqual(expected); - }); - it('should not find the element', function() { - expected = -1; - actual = testSubject.lastIndexOf('mus'); - expect(actual).toEqual(expected); - }); - it('should find undefined as well', function() { - expected = -1; - actual = testSubject.lastIndexOf(undefined); - expect(actual).not.toEqual(expected); - }); - it('should skip unset indexes', function() { - expected = 2; - actual = testSubject.lastIndexOf(undefined); - expect(actual).toEqual(expected); - }); - it('should use a strict test', function() { - actual = testSubject.lastIndexOf(null); - expect(actual).toEqual(5); - - actual = testSubject.lastIndexOf('2'); - expect(actual).toEqual(-1); - }); - it('should skip the first if fromIndex is set', function() { - expect(testSubject.lastIndexOf(2, 2)).toEqual(0); - expect(testSubject.lastIndexOf(2, 0)).toEqual(0); - expect(testSubject.lastIndexOf(2, 6)).toEqual(6); - }); - it('should work with negative fromIndex', function() { - expect(testSubject.lastIndexOf(2, -3)).toEqual(6); - expect(testSubject.lastIndexOf(2, -9)).toEqual(0); - }); - it('should work with fromIndex being greater than the length', function() { - expect(testSubject.lastIndexOf(2, 20)).toEqual(6); - }); - it('should work with fromIndex being negative and greater than the length', function() { - expect(testSubject.lastIndexOf(2, -20)).toEqual(-1); - }); - }); - - describe('Array like', function() { - var lastIndexOf = Array.prototype.lastIndexOf, - testAL; - beforeEach(function() { - testAL = {}; - testSubject.forEach(function (o,i) { - testAL[i] = o; - }); - testAL.length = testSubject.length; - }); - it('should find the element (array-like)', function() { - expected = 4; - actual = lastIndexOf.call(testAL, 'hej'); - expect(actual).toEqual(expected); - }); - it('should not find the element (array-like)', function() { - expected = -1; - actual = lastIndexOf.call(testAL, 'mus'); - expect(actual).toEqual(expected); - }); - it('should find undefined as well (array-like)', function() { - expected = -1; - actual = lastIndexOf.call(testAL, undefined); - expect(actual).not.toEqual(expected); - }); - it('should skip unset indexes (array-like)', function() { - expected = 2; - actual = lastIndexOf.call(testAL, undefined); - expect(actual).toEqual(expected); - }); - it('should use a strict test (array-like)', function() { - actual = lastIndexOf.call(testAL, null); - expect(actual).toEqual(5); - - actual = lastIndexOf.call(testAL, '2'); - expect(actual).toEqual(-1); - }); - it('should skip the first if fromIndex is set', function() { - expect(lastIndexOf.call(testAL, 2, 2)).toEqual(0); - expect(lastIndexOf.call(testAL, 2, 0)).toEqual(0); - expect(lastIndexOf.call(testAL, 2, 6)).toEqual(6); - }); - it('should work with negative fromIndex', function() { - expect(lastIndexOf.call(testAL, 2, -3)).toEqual(6); - expect(lastIndexOf.call(testAL, 2, -9)).toEqual(0); - }); - it('should work with fromIndex being greater than the length', function() { - expect(lastIndexOf.call(testAL, 2, 20)).toEqual(6); - }); - it('should work with fromIndex being negative and greater than the length', function() { - expect(lastIndexOf.call(testAL, 2, -20)).toEqual(-1); - }); - }); - }); - - describe('filter', function() { - var filteredArray, - callback = function callback(o, i, arr) { - return ( - i != 3 && i != 5 - ); - }; - - beforeEach(function() { - testSubject = [2, 3, undefined, true, 'hej', 3, null, false, 0]; - delete testSubject[1]; - filteredArray = [2, undefined, 'hej', null, false, 0]; - }); - describe('Array object', function() { - - it('should call the callback with the proper arguments', function() { - var callback = jasmine.createSpy('callback'), - arr = ['1']; - arr.filter(callback); - expect(callback).toHaveBeenCalledWith('1', 0, arr); - }); - it('should not affect elements added to the array after it has begun', function() { - var arr = [1,2,3], - i = 0; - arr.filter(function(a) { - i++; - if(i <= 4) { - arr.push(a+3); - } - return true; - }); - expect(arr).toEqual([1,2,3,4,5,6]); - expect(i).toBe(3); - }); - it('should skip non-set values', function() { - var passedValues = {}; - testSubject = [1,2,3,4]; - delete testSubject[1]; - testSubject.filter(function(o, i) { - passedValues[i] = o; - return true; - }); - expect(passedValues).toExactlyMatch(testSubject); - }); - it('should pass the right context to the filter', function() { - var passedValues = {}; - testSubject = [1,2,3,4]; - delete testSubject[1]; - testSubject.filter(function(o, i) { - this[i] = o; - return true; - }, passedValues); - expect(passedValues).toExactlyMatch(testSubject); - }); - it('should set the right context when given none', function() { - var context; - [1].filter(function() {context = this;}); - expect(context).toBe(function() {return this}.call()); - }); - it('should remove only the values for which the callback returns false', function() { - var result = testSubject.filter(callback); - expect(result).toExactlyMatch(filteredArray); - }); - it('should leave the original array untouched', function() { - var copy = testSubject.slice(); - testSubject.filter(callback); - expect(testSubject).toExactlyMatch(copy); - }); - it('should not be affected by same-index mutation', function () { - var results = [1, 2, 3] - .filter(function (value, index, array) { - array[index] = 'a'; - return true; - }); - expect(results).toEqual([1, 2, 3]); - }); - }); - describe('Array like', function() { - beforeEach(function() { - testSubject = createArrayLikeFromArray(testSubject); - }); - it('should call the callback with the proper arguments', function() { - var callback = jasmine.createSpy('callback'), - arr = createArrayLikeFromArray(['1']); - Array.prototype.filter.call(arr, callback); - expect(callback).toHaveBeenCalledWith('1', 0, arr); - }); - it('should not affect elements added to the array after it has begun', function() { - var arr = createArrayLikeFromArray([1,2,3]), - i = 0; - Array.prototype.filter.call(arr, function(a) { - i++; - if(i <= 4) { - arr[i+2] = a+3; - } - return true; - }); - delete arr.length; - expect(arr).toExactlyMatch([1,2,3,4,5,6]); - expect(i).toBe(3); - }); - it('should skip non-set values', function() { - var passedValues = {}; - testSubject = createArrayLikeFromArray([1,2,3,4]); - delete testSubject[1]; - Array.prototype.filter.call(testSubject, function(o, i) { - passedValues[i] = o; - return true; - }); - delete testSubject.length; - expect(passedValues).toExactlyMatch(testSubject); - }); - it('should set the right context when given none', function() { - var context; - Array.prototype.filter.call(createArrayLikeFromArray([1]), function() {context = this;}, undefined); - expect(context).toBe(function() {return this}.call()); - }); - it('should pass the right context to the filter', function() { - var passedValues = {}; - testSubject = createArrayLikeFromArray([1,2,3,4]); - delete testSubject[1]; - Array.prototype.filter.call(testSubject, function(o, i) { - this[i] = o; - return true; - }, passedValues); - delete testSubject.length; - expect(passedValues).toExactlyMatch(testSubject); - }); - it('should remove only the values for which the callback returns false', function() { - var result = Array.prototype.filter.call(testSubject, callback); - expect(result).toExactlyMatch(filteredArray); - }); - it('should leave the original array untouched', function() { - var copy = createArrayLikeFromArray(testSubject); - Array.prototype.filter.call(testSubject, callback); - expect(testSubject).toExactlyMatch(copy); - }); - }); - }); - describe('map', function() { - var callback; - beforeEach(function() { - var i = 0; - callback = function() { - return i++; - }; - }); - describe('Array object', function() { - it('should call callback with the right parameters', function() { - var callback = jasmine.createSpy('callback'), - array = [1]; - array.map(callback); - expect(callback).toHaveBeenCalledWith(1, 0, array); - }); - it('should set the context correctly', function() { - var context = {}; - testSubject.map(function(o,i) { - this[i] = o; - }, context); - expect(context).toExactlyMatch(testSubject); - }); - it('should set the right context when given none', function() { - var context; - [1].map(function() {context = this;}); - expect(context).toBe(function() {return this}.call()); - }); - it('should not change the array it is called on', function() { - var copy = testSubject.slice(); - testSubject.map(callback); - expect(testSubject).toExactlyMatch(copy); - }); - it('should only run for the number of objects in the array when it started', function() { - var arr = [1,2,3], - i = 0; - arr.map(function(o) { - arr.push(o+3); - i++; - return o; - }); - expect(arr).toExactlyMatch([1,2,3,4,5,6]); - expect(i).toBe(3); - }); - it('should properly translate the values as according to the callback', function() { - var result = testSubject.map(callback), - expected = [0,0,1,2,3,4,5,6]; - delete expected[1]; - expect(result).toExactlyMatch(expected); - }); - it('should skip non-existing values', function() { - var array = [1,2,3,4], - i = 0; - delete array[2]; - array.map(function() { - i++; - }); - expect(i).toBe(3); - }); - }); - describe('Array-like', function() { - beforeEach(function() { - testSubject = createArrayLikeFromArray(testSubject); - }); - it('should call callback with the right parameters', function() { - var callback = jasmine.createSpy('callback'), - array = createArrayLikeFromArray([1]); - Array.prototype.map.call(array, callback); - expect(callback).toHaveBeenCalledWith(1, 0, array); - }); - it('should set the context correctly', function() { - var context = {}; - Array.prototype.map.call(testSubject, function(o,i) { - this[i] = o; - }, context); - delete testSubject.length; - expect(context).toExactlyMatch(testSubject); - }); - it('should set the right context when given none', function() { - var context; - Array.prototype.map.call(createArrayLikeFromArray([1]), function() {context = this;}); - expect(context).toBe(function() {return this}.call()); - }); - it('should not change the array it is called on', function() { - var copy = createArrayLikeFromArray(testSubject); - Array.prototype.map.call(testSubject, callback); - expect(testSubject).toExactlyMatch(copy); - }); - it('should only run for the number of objects in the array when it started', function() { - var arr = createArrayLikeFromArray([1,2,3]), - i = 0; - Array.prototype.map.call(arr, function(o) { - Array.prototype.push.call(arr, o+3); - i++; - return o; - }); - delete arr.length; - expect(arr).toExactlyMatch([1,2,3,4,5,6]); - expect(i).toBe(3); - }); - it('should properly translate the values as according to the callback', function() { - var result = Array.prototype.map.call(testSubject, callback), - expected = [0,0,1,2,3,4,5,6]; - delete expected[1]; - expect(result).toExactlyMatch(expected); - }); - it('should skip non-existing values', function() { - var array = createArrayLikeFromArray([1,2,3,4]), - i = 0; - delete array[2]; - Array.prototype.map.call(array, function() { - i++; - }); - expect(i).toBe(3); - }); - }); - }); - - describe('reduce', function() { - beforeEach(function() { - testSubject = [1,2,3]; - }); - - describe('Array', function() { - it('should pass the correct arguments to the callback', function() { - var spy = jasmine.createSpy().andReturn(0); - testSubject.reduce(spy); - expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]); - }); - it('should start with the right initialValue', function() { - var spy = jasmine.createSpy().andReturn(0); - testSubject.reduce(spy, 0); - expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]); - }); - it('should not affect elements added to the array after it has begun', function() { - var arr = [1,2,3], - i = 0; - arr.reduce(function(a, b) { - i++; - if(i <= 4) { - arr.push(a+3); - }; - return b; - }); - expect(arr).toEqual([1,2,3,4,5]); - expect(i).toBe(2); - }); - it('should work as expected for empty arrays', function() { - var spy = jasmine.createSpy(); - expect(function() { - [].reduce(spy); - }).toThrow(); - expect(spy).not.toHaveBeenCalled(); - }); - it('should throw correctly if no callback is given', function() { - expect(function() { - testSubject.reduce(); - }).toThrow(); - }); - it('should return the expected result', function() { - expect(testSubject.reduce(function(a,b) { - return (a||'').toString()+(b||'').toString(); - })).toEqual(testSubject.join('')); - }); - it('should not directly affect the passed array', function() { - var copy = testSubject.slice(); - testSubject.reduce(function(a,b) { - return a+b; - }); - expect(testSubject).toEqual(copy); - }); - it('should skip non-set values', function() { - delete testSubject[1]; - var visited = {}; - testSubject.reduce(function(a,b) { - if(a) - visited[a] = true; - if(b) - visited[b] = true; - return 0; - }); - - expect(visited).toEqual({ '1': true, '3': true }); - }); - it('should have the right length', function() { - expect(testSubject.reduce.length).toBe(1); - }); - }); - describe('Array-like objects', function() { - beforeEach(function() { - testSubject = createArrayLikeFromArray(testSubject); - testSubject.reduce = Array.prototype.reduce; - }); - it('should pass the correct arguments to the callback', function() { - var spy = jasmine.createSpy().andReturn(0); - testSubject.reduce(spy); - expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]); - }); - it('should start with the right initialValue', function() { - var spy = jasmine.createSpy().andReturn(0); - testSubject.reduce(spy, 0); - expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]); - }); - it('should not affect elements added to the array after it has begun', function() { - var arr = createArrayLikeFromArray([1,2,3]), - i = 0; - Array.prototype.reduce.call(arr, function(a, b) { - i++; - if(i <= 4) { - arr[i+2] = a+3; - }; - return b; - }); - expect(arr).toEqual({ - 0: 1, - 1: 2, - 2: 3, - 3: 4, - 4: 5, - length: 3 - }); - expect(i).toBe(2); - }); - it('should work as expected for empty arrays', function() { - var spy = jasmine.createSpy(); - expect(function() { - Array.prototype.reduce.call({length: 0}, spy); - }).toThrow(); - expect(spy).not.toHaveBeenCalled(); - }); - it('should throw correctly if no callback is given', function() { - expect(function() { - testSubject.reduce(); - }).toThrow(); - }); - it('should return the expected result', function() { - expect(testSubject.reduce(function(a,b) { - return (a||'').toString()+(b||'').toString(); - })).toEqual('123'); - }); - it('should not directly affect the passed array', function() { - var copy = createArrayLikeFromArray(testSubject); - testSubject.reduce(function(a,b) { - return a+b; - }); - delete(testSubject.reduce); - expect(testSubject).toEqual(copy); - }); - it('should skip non-set values', function() { - delete testSubject[1]; - var visited = {}; - testSubject.reduce(function(a,b) { - if(a) - visited[a] = true; - if(b) - visited[b] = true; - return 0; - }); - - expect(visited).toEqual({ '1': true, '3': true }); - }); - it('should have the right length', function() { - expect(testSubject.reduce.length).toBe(1); - }); - }); - }); - describe('reduceRight', function() { - beforeEach(function() { - testSubject = [1,2,3]; - }); - - describe('Array', function() { - it('should pass the correct arguments to the callback', function() { - var spy = jasmine.createSpy().andReturn(0); - testSubject.reduceRight(spy); - expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]); - }); - it('should start with the right initialValue', function() { - var spy = jasmine.createSpy().andReturn(0); - testSubject.reduceRight(spy, 0); - expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]); - }); - it('should not affect elements added to the array after it has begun', function() { - var arr = [1,2,3], - i = 0; - arr.reduceRight(function(a, b) { - i++; - if(i <= 4) { - arr.push(a+3); - }; - return b; - }); - expect(arr).toEqual([1,2,3,6,5]); - expect(i).toBe(2); - }); - it('should work as expected for empty arrays', function() { - var spy = jasmine.createSpy(); - expect(function() { - [].reduceRight(spy); - }).toThrow(); - expect(spy).not.toHaveBeenCalled(); - }); - it('should work as expected for empty arrays with an initial value', function() { - var spy = jasmine.createSpy(), - result; - - result = [].reduceRight(spy, ''); - expect(spy).not.toHaveBeenCalled(); - expect(result).toBe(''); - }); - it('should throw correctly if no callback is given', function() { - expect(function() { - testSubject.reduceRight(); - }).toThrow(); - }); - it('should return the expected result', function() { - expect(testSubject.reduceRight(function(a,b) { - return (a||'').toString()+(b||'').toString(); - })).toEqual('321'); - }); - it('should not directly affect the passed array', function() { - var copy = testSubject.slice(); - testSubject.reduceRight(function(a,b) { - return a+b; - }); - expect(testSubject).toEqual(copy); - }); - it('should skip non-set values', function() { - delete testSubject[1]; - var visited = {}; - testSubject.reduceRight(function(a,b) { - if(a) - visited[a] = true; - if(b) - visited[b] = true; - return 0; - }); - - expect(visited).toEqual({ '1': true, '3': true }); - }); - it('should have the right length', function() { - expect(testSubject.reduceRight.length).toBe(1); - }); - }); - describe('Array-like objects', function() { - beforeEach(function() { - testSubject = createArrayLikeFromArray(testSubject); - testSubject.reduceRight = Array.prototype.reduceRight; - }); - it('should pass the correct arguments to the callback', function() { - var spy = jasmine.createSpy().andReturn(0); - testSubject.reduceRight(spy); - expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]); - }); - it('should start with the right initialValue', function() { - var spy = jasmine.createSpy().andReturn(0); - testSubject.reduceRight(spy, 0); - expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]); - }); - it('should not affect elements added to the array after it has begun', function() { - var arr = createArrayLikeFromArray([1,2,3]), - i = 0; - Array.prototype.reduceRight.call(arr, function(a, b) { - i++; - if(i <= 4) { - arr[i+2] = a+3; - }; - return b; - }); - expect(arr).toEqual({ - 0: 1, - 1: 2, - 2: 3, - 3: 6, - 4: 5, - length: 3 // does not get updated on property assignment - }); - expect(i).toBe(2); - }); - it('should work as expected for empty arrays', function() { - var spy = jasmine.createSpy(); - expect(function() { - Array.prototype.reduceRight.call({length:0}, spy); - }).toThrow(); - expect(spy).not.toHaveBeenCalled(); - }); - it('should throw correctly if no callback is given', function() { - expect(function() { - testSubject.reduceRight(); - }).toThrow(); - }); - it('should return the expected result', function() { - expect(testSubject.reduceRight(function(a,b) { - return (a||'').toString()+(b||'').toString(); - })).toEqual('321'); - }); - it('should not directly affect the passed array', function() { - var copy = createArrayLikeFromArray(testSubject); - testSubject.reduceRight(function(a,b) { - return a+b; - }); - delete(testSubject.reduceRight); - expect(testSubject).toEqual(copy); - }); - it('should skip non-set values', function() { - delete testSubject[1]; - var visited = {}; - testSubject.reduceRight(function(a,b) { - if(a) - visited[a] = true; - if(b) - visited[b] = true; - return 0; - }); - - expect(visited).toEqual({ '1': true, '3': true }); - }); - it('should have the right length', function() { - expect(testSubject.reduceRight.length).toBe(1); - }); - }); - }); - - describe('isArray', function () { - it('should work for Array', function () { - var ret = Array.isArray([]); - - expect(ret).toBe(true); - }); - - it('should fail for other objects', function () { - var objects = [ - "someString", - true, - false, - 42, - 0, - {}, - Object.create && Object.create(null) || null, - /foo/, - arguments, - document.getElementsByTagName("div") - ]; - - objects.forEach(function (v) { - expect(Array.isArray(v)).toBe(false); - }); - }); - }); - - describe('unshift', function () { - it('should return length', function () { - expect([].unshift(0)).toEqual(1); - }); - }); - - describe('splice', function () { - var b = ["b"], - a = [1, "a", b], - test; - - var makeArray = function(l, prefix) { - prefix = prefix || ""; - var a = []; - while (l--) { - a.unshift(prefix + Array(l + 1).join(" ") + l) - } - return a - }; - - beforeEach(function() { - test = a.slice(0); - }); - - it('basic implementation test 1', function () { - expect(test.splice(0)).toEqual(a); - }); - it('basic implementation test 2', function () { - test.splice(0, 2); - expect(test).toEqual([b]); - }); - - it('should return right result 1', function () { - expect((function() { - var array = []; - - array.splice(0, 0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20); - array.splice(1, 0, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21","F22", "F23", "F24", "F25", "F26"); - array.splice(5, 0, "XXX"); - - return array.join("|"); - }())).toBe("1|F1|F2|F3|F4|XXX|F5|F6|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20"); - }); - - it('should return right result 2', function () { - expect((function() { - var array = makeArray(6); - - array.splice(array.length - 1, 1, ""); - array.splice(0, 1, 1,2,3,4); - array.splice(0, 0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20, 21, 22, 23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45); - - array.splice(4, 0, "99999999999999"); - return array.join("|"); - }())).toBe("1|2|3|4|99999999999999|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|1|2|3|4| 1| 2| 3| 4|"); - }); - - it('should return right result 3', function () { - expect((function() { - var array = [1,2,3]; - - array.splice(0); - array.splice(0, 1, 1,2,3,4,5,6,7,8,9,10); - array.splice(1, 1, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21","F22", "F23", "F24", "F25", "F26"); - array.splice(5, 1, "YYY", "XXX"); - array.splice(0, 1); - array.splice(0, 2); - array.pop(); - array.push.apply(array, makeArray(10, "-")); - array.splice(array.length - 2, 10); - array.splice(); - array.splice(1, 1, 1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9); - array.splice(1, 1, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21","F22", "F23", "F24", "F25", "F26",1,23,4,5,6,7,8); - array.splice(30, 10); - array.splice(30, 1); - array.splice(30, 0); - array.splice(2, 5, 1,2,3,"P", "LLL", "CCC", "YYY", "XXX"); - array.push(1,2,3,4,5,6); - array.splice(1, 6, 1,2,3,4,5,6,7,8,9,4,5,6,7,8,9); - array.splice(3, 7); - array.unshift(7,8,9,10,11); - array.pop(); - array.splice(5, 2); - array.pop(); - array.unshift.apply(array, makeArray(8, "~")); - array.pop(); - array.splice(3, 1, "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21","F22", "F23", "F24", "F25", "F26",1,23,4,5,6,7,8); - array.splice(4, 5, "P", "LLL", "CCC", "YYY", "XXX"); - - return array.join("|"); - }())).toBe("~0|~ 1|~ 2|F1|P|LLL|CCC|YYY|XXX|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|1|23|4|5|6|7|8|~ 4|~ 5|~ 6|~ 7|7|8|9|10|11|2|4|5|6|7|8|9|CCC|YYY|XXX|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|1|23|4|9|10|1|2|3|4|5|6|7|8|9|YYY|XXX|F6|F7|F8|F9|F10|F11|F12|F13|F14|F15|F16|F17|F18|F19|F20|F21|F22|F23|F24|F25|F26|3|4|5|6|7|8|9|-0|- 1|- 2|- 3|- 4|- 5|- 6|- 7|1|2|3"); - }); - - - it('should do nothing if method called with no arguments', function () { - expect(test.splice()).toEqual([]); - expect(test).toEqual(a); - }); - //TODO:: Is this realy TRUE behavior? - it('should set first argument to 0 if first argument is set but undefined', function () { - var test2 = test.slice(0); - expect(test.splice(void 0, 2)).toEqual(test2.splice(0, 2)); - expect(test).toEqual(test2); - }); - - it('should deleted and return all items after "start" when second argument is undefined', function () { - expect(test.splice(0)).toEqual(a); - expect(test).toEqual([]); - }); - it('should deleted and return all items after "start" when second argument is undefined', function () { - expect(test.splice(2)).toEqual([b]); - expect(test).toEqual([1, "a"]); - }); - it('runshould have the right length', function () { - expect(test.splice.length).toBe(2); - }); - }); - - -}); diff --git a/dist/bower_components/es5-shim/tests/spec/s-date.js b/dist/bower_components/es5-shim/tests/spec/s-date.js deleted file mode 100644 index a2e288c6f..000000000 --- a/dist/bower_components/es5-shim/tests/spec/s-date.js +++ /dev/null @@ -1,152 +0,0 @@ -describe('Date', function () { - - describe('now', function () { - it('should be the current time', function () { - expect(Date.now() === new Date().getTime()).toBe(true); - }); - }); - - describe("parse", function () { - // TODO: Write the rest of the test. - - it('should support extended years', function () { - - expect(Date.parse('0001-01-01T00:00:00Z')).toBe(-62135596800000); - expect(Date.parse('+275760-09-13T00:00:00.000Z')).toBe(8.64e15); - expect(Date.parse('+033658-09-27T01:46:40.000Z')).toBe(1e15); - expect(Date.parse('-000001-01-01T00:00:00Z')).toBe(-62198755200000); - expect(Date.parse('+002009-12-15T00:00:00Z')).toBe(1260835200000); - - }); - - it('should work', function () { - //Chrome 19 Opera 12 Firefox 11 IE 9 Safari 5.1.1 - expect(Date.parse("2012-11-31T23:59:59.000Z")).toBeFalsy(); //1354406399000 NaN NaN 1354406399000 NaN - expect(Date.parse("2012-12-31T23:59:59.000Z")).toBe(1356998399000); //1356998399000 1356998399000 1356998399000 1356998399000 1356998399000 - expect(Date.parse("2012-12-31T23:59:60.000Z")).toBeFalsy(); //NaN NaN NaN NaN 1356998400000 - expect(Date.parse("2012-04-04T05:02:02.170Z")).toBe(1333515722170); //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 - expect(Date.parse("2012-04-04T05:02:02.170999Z")).toBe(1333515722170); //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 - expect(Date.parse("2012-04-04T05:02:02.17Z")).toBe(1333515722170); //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 - expect(Date.parse("2012-04-04T05:02:02.1Z")).toBe(1333515722100); //1333515722170 1333515722170 1333515722170 1333515722170 1333515722170 - expect(Date.parse("2012-04-04T24:00:00.000Z")).toBe(1333584000000); //NaN 1333584000000 1333584000000 1333584000000 1333584000000 - expect(Date.parse("2012-04-04T24:00:00.500Z")).toBeFalsy(); //NaN NaN 1333584000500 1333584000500 NaN - expect(Date.parse("2012-12-31T10:08:60.000Z")).toBeFalsy(); //NaN NaN NaN NaN 1356948540000 - expect(Date.parse("2012-13-01T12:00:00.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN - expect(Date.parse("2012-12-32T12:00:00.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN - expect(Date.parse("2012-12-31T25:00:00.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN - expect(Date.parse("2012-12-31T24:01:00.000Z")).toBeFalsy(); //NaN NaN NaN 1356998460000 NaN - expect(Date.parse("2012-12-31T12:60:00.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN - expect(Date.parse("2012-12-31T12:00:60.000Z")).toBeFalsy(); //NaN NaN NaN NaN 1356955260000 - expect(Date.parse("2012-00-31T23:59:59.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN - expect(Date.parse("2012-12-00T23:59:59.000Z")).toBeFalsy(); //NaN NaN NaN NaN NaN - expect(Date.parse("2012-02-29T12:00:00.000Z")).toBe(1330516800000); //1330516800000 1330516800000 1330516800000 1330516800000 1330516800000 - expect(Date.parse("2011-02-29T12:00:00.000Z")).toBeFalsy(); //1298980800000 NaN NaN 1298980800000 NaN - expect(Date.parse("2011-03-01T12:00:00.000Z")).toBe(1298980800000); //1298980800000 1298980800000 1298980800000 1298980800000 1298980800000 - - // extended years: - expect(Date.parse("0000-01-01T00:00:00.000Z")).toBe(-621672192e5); //-621672192e5 -621672192e5 -621672192e5 -621672192e5 -621672192e5 - expect(Date.parse("+275760-09-13T00:00:00.000Z")).toBe(8.64e15); //8.64e15 NaN 8.64e15 8.64e15 8.64e15 - expect(Date.parse("-271821-04-20T00:00:00.000Z")).toBe(-8.64e15); //-8.64e15 NaN -8.64e15 -8.64e15 -8.6400000864e15 - expect(Date.parse("+275760-09-13T00:00:00.001Z")).toBeFalsy(); //NaN NaN NaN 8.64e15 + 1 8.64e15 + 1 - expect(Date.parse("-271821-04-19T23:59:59.999Z")).toBeFalsy(); //NaN NaN NaN -8.64e15 - 1 -8.6400000864e15 - 1 - - // https://github.com/kriskowal/es5-shim/issues/80 Safari bug with leap day - expect(Date.parse("2034-03-01T00:00:00.000Z") - - Date.parse("2034-02-27T23:59:59.999Z")).toBe(86400001); //86400001 86400001 86400001 86400001 1 - - // Time Zone Offset - expect(Date.parse("2012-01-29T12:00:00.000+01:00")).toBe(132783480e4);//132783480e4 132783480e4 132783480e4 132783480e4 132783480e4 - expect(Date.parse("2012-01-29T12:00:00.000-00:00")).toBe(132783840e4);//132783840e4 132783840e4 132783840e4 132783840e4 132783840e4 - expect(Date.parse("2012-01-29T12:00:00.000+00:00")).toBe(132783840e4);//132783840e4 132783840e4 132783840e4 132783840e4 132783840e4 - expect(Date.parse("2012-01-29T12:00:00.000+23:59")).toBe(132775206e4);//132775206e4 132775206e4 132775206e4 132775206e4 132775206e4 - expect(Date.parse("2012-01-29T12:00:00.000-23:59")).toBe(132792474e4);//132792474e4 132792474e4 132792474e4 132792474e4 132792474e4 - expect(Date.parse("2012-01-29T12:00:00.000+24:00")).toBeFalsy(); //NaN 1327752e6 NaN 1327752000000 1327752000000 - expect(Date.parse("2012-01-29T12:00:00.000+24:01")).toBeFalsy(); //NaN NaN NaN 1327751940000 1327751940000 - expect(Date.parse("2012-01-29T12:00:00.000+24:59")).toBeFalsy(); //NaN NaN NaN 1327748460000 1327748460000 - expect(Date.parse("2012-01-29T12:00:00.000+25:00")).toBeFalsy(); //NaN NaN NaN NaN NaN - expect(Date.parse("2012-01-29T12:00:00.000+00:60")).toBeFalsy(); //NaN NaN NaN NaN NaN - expect(Date.parse("-271821-04-20T00:00:00.000+00:01")).toBeFalsy(); //NaN NaN NaN -864000000006e4 -864000008646e4 - expect(Date.parse("-271821-04-20T00:01:00.000+00:01")).toBe(-8.64e15);//-8.64e15 NaN -8.64e15 -8.64e15 -864000008640e4 - - // When time zone is missed, local offset should be used (ES 5.1 bug) - // see https://bugs.ecmascript.org/show_bug.cgi?id=112 - var tzOffset = Number(new Date(1970, 0)); - // same as (new Date().getTimezoneOffset() * 60000) - expect(Date.parse('1970-01-01T00:00:00')).toBe(tzOffset); //tzOffset 0 0 0 NaN - }); - - it("should be able to coerce to a number", function(){ - var actual = Number(new Date(1970, 0)); - var expected = parseInt(actual, 10); - expect(actual).toBeDefined(); - expect(actual).toEqual(expected); - expect(isNaN(actual)).toBeFalsy(); - }); - - }); - - describe("toString", function(){ - var actual = (new Date(1970, 0)).toString(); - beforeEach(function(){ - actual = (new Date(1970, 0)).toString(); - }); - it("should show correct date info for "+actual, function(){ - expect(actual).toMatch(/1970/); - expect(actual).toMatch(/jan/i); - expect(actual).toMatch(/thu/i); - expect(actual).toMatch(/00:00:00/); - }); - }); - - describe("valueOf", function(){ - var actual = (new Date(1970, 0)); - beforeEach(function(){ - actual = (new Date(1970, 0)).valueOf(); - }); - it("should give an int value", function(){ - expect(parseInt(actual, 10)).toBeTruthy(); - }); - }); - - describe("toISOString", function () { - // TODO: write the rest of the test. - - it('should support extended years', function () { - expect(new Date(-62198755200000).toISOString().indexOf('-000001-01-01')).toBe(0); - expect(new Date(8.64e15).toISOString().indexOf('+275760-09-13')).toBe(0); - }); - - it('should return correct dates', function () { - expect(new Date(-1).toISOString()).toBe('1969-12-31T23:59:59.999Z');// Safari 5.1.5 "1969-12-31T23:59:59.-01Z" - expect(new Date(-3509827334573292).toISOString()).toBe('-109252-01-01T10:37:06.708Z'); // Opera 11.61/Opera 12 bug with Date#getUTCMonth - }); - - }); - - describe("toJSON", function () { - - // Opera 11.6x/12 bug - it('should call toISOString', function () { - var date = new Date(0); - date.toISOString = function () { - return 1; - }; - expect(date.toJSON()).toBe(1); - }); - - it('should return null for not finite dates', function () { - var date = new Date(NaN), - json; - try { - json = date.toJSON(); - } catch (e) {} - expect(json).toBe(null); - }); - - it('should return the isoString when stringified', function () { - var date = new Date(); - expect(JSON.stringify(date.toISOString())).toBe(JSON.stringify(date)); - }) - }); - -}); \ No newline at end of file diff --git a/dist/bower_components/es5-shim/tests/spec/s-function.js b/dist/bower_components/es5-shim/tests/spec/s-function.js deleted file mode 100644 index aa4361e7d..000000000 --- a/dist/bower_components/es5-shim/tests/spec/s-function.js +++ /dev/null @@ -1,147 +0,0 @@ - -describe('Function', function() { - "use strict"; - describe('bind', function() { - var actual, expected, - testSubject; - - testSubject = { - push: function(o) { - this.a.push(o); - } - }; - - function func() { - Array.prototype.forEach.call(arguments, function(a) { - this.push(a); - }, this); - return this; - }; - - beforeEach(function() { - actual = []; - testSubject.a = []; - }); - - it('binds properly without a context', function() { - var context; - testSubject.func = function() { - context = this; - }.bind(); - testSubject.func(); - expect(context).toBe(function() {return this}.call()); - }); - it('binds properly without a context, and still supplies bound arguments', function() { - var a, context; - testSubject.func = function() { - a = Array.prototype.slice.call(arguments); - context = this; - }.bind(undefined, 1,2,3); - testSubject.func(1,2,3); - expect(a).toEqual([1,2,3,1,2,3]); - expect(context).toBe(function() {return this}.call()); - }); - it('binds a context properly', function() { - testSubject.func = func.bind(actual); - testSubject.func(1,2,3); - expect(actual).toEqual([1,2,3]); - expect(testSubject.a).toEqual([]); - }); - it('binds a context and supplies bound arguments', function() { - testSubject.func = func.bind(actual, 1,2,3); - testSubject.func(4,5,6); - expect(actual).toEqual([1,2,3,4,5,6]); - expect(testSubject.a).toEqual([]); - }); - - it('returns properly without binding a context', function() { - testSubject.func = function() { - return this; - }.bind(); - var context = testSubject.func(); - expect(context).toBe(function() {return this}.call()); - }); - it('returns properly without binding a context, and still supplies bound arguments', function() { - var context; - testSubject.func = function() { - context = this; - return Array.prototype.slice.call(arguments); - }.bind(undefined, 1,2,3); - actual = testSubject.func(1,2,3); - expect(context).toBe(function() {return this}.call()); - expect(actual).toEqual([1,2,3,1,2,3]); - }); - it('returns properly while binding a context properly', function() { - var ret; - testSubject.func = func.bind(actual); - ret = testSubject.func(1,2,3); - expect(ret).toBe(actual); - expect(ret).not.toBe(testSubject); - }); - it('returns properly while binding a context and supplies bound arguments', function() { - var ret; - testSubject.func = func.bind(actual, 1,2,3); - ret = testSubject.func(4,5,6); - expect(ret).toBe(actual); - expect(ret).not.toBe(testSubject); - }); - it('passes the correct arguments as a constructor', function() { - var ret, expected = { name: "Correct" }; - testSubject.func = function(arg) { - return arg; - }.bind({ name: "Incorrect" }); - ret = new testSubject.func(expected); - expect(ret).toBe(expected); - }); - it('returns the return value of the bound function when called as a constructor', function () { - var oracle = [1, 2, 3]; - var subject = function () { - return oracle; - }.bind(null); - var result = new subject; - expect(result).toBe(oracle); - }); - it('returns the correct value if constructor returns primitive', function() { - var oracle = [1, 2, 3]; - var subject = function () { - return oracle; - }.bind(null); - var result = new subject; - expect(result).toBe(oracle); - - oracle = {}; - result = new subject; - expect(result).toBe(oracle); - - oracle = function(){}; - result = new subject; - expect(result).toBe(oracle); - - oracle = "asdf"; - result = new subject; - expect(result).not.toBe(oracle); - - oracle = null; - result = new subject; - expect(result).not.toBe(oracle); - - oracle = true; - result = new subject; - expect(result).not.toBe(oracle); - - oracle = 1; - result = new subject; - expect(result).not.toBe(oracle); - }); - it('returns the value that instance of original "class" when called as a constructor', function() { - var classA = function(x) { - this.name = x || "A"; - } - var classB = classA.bind(null, "B"); - - var result = new classB; - expect(result instanceof classA).toBe(true); - expect(result instanceof classB).toBe(true); - }); - }); -}); diff --git a/dist/bower_components/es5-shim/tests/spec/s-number.js b/dist/bower_components/es5-shim/tests/spec/s-number.js deleted file mode 100644 index b09ae2b92..000000000 --- a/dist/bower_components/es5-shim/tests/spec/s-number.js +++ /dev/null @@ -1,14 +0,0 @@ -describe('Number', function () { - 'use strict'; - - describe('toFixed', function () { - it('should convert numbers correctly', function () { - expect((0.00008).toFixed(3)).toBe('0.000'); - expect((0.9).toFixed(0)).toBe('1'); - expect((1.255).toFixed(2)).toBe('1.25'); - expect((1843654265.0774949).toFixed(5)).toBe('1843654265.07749'); - expect((1000000000000000128).toFixed(0)).toBe('1000000000000000128'); - }); - }); - -}); diff --git a/dist/bower_components/es5-shim/tests/spec/s-object.js b/dist/bower_components/es5-shim/tests/spec/s-object.js deleted file mode 100644 index 4c540bf9b..000000000 --- a/dist/bower_components/es5-shim/tests/spec/s-object.js +++ /dev/null @@ -1,181 +0,0 @@ -describe('Object', function () { - "use strict"; - - describe("Object.keys", function () { - var obj = { - "str": "boz", - "obj": { }, - "arr": [], - "bool": true, - "num": 42, - "null": null, - "undefined": undefined - }; - - var loopedValues = []; - for (var k in obj) { - loopedValues.push(k); - } - - var keys = Object.keys(obj); - it('should have correct length', function () { - expect(keys.length).toBe(7); - }); - - it('should return an Array', function () { - expect(Array.isArray(keys)).toBe(true); - }); - - it('should return names which are own properties', function () { - keys.forEach(function (name) { - expect(obj.hasOwnProperty(name)).toBe(true); - }); - }); - - it('should return names which are enumerable', function () { - keys.forEach(function (name) { - expect(loopedValues.indexOf(name)).toNotBe(-1); - }) - }); - - it('should throw error for non object', function () { - var e = {}; - expect(function () { - try { - Object.keys(42) - } catch (err) { - throw e; - } - }).toThrow(e); - }); - }); - - describe("Object.isExtensible", function () { - var obj = { }; - - it('should return true if object is extensible', function () { - expect(Object.isExtensible(obj)).toBe(true); - }); - - it('should return false if object is not extensible', function () { - expect(Object.isExtensible(Object.preventExtensions(obj))).toBe(false); - }); - - it('should return false if object is seal', function () { - expect(Object.isExtensible(Object.seal(obj))).toBe(false); - }); - - it('should return false if object is freeze', function () { - expect(Object.isExtensible(Object.freeze(obj))).toBe(false); - }); - - it('should throw error for non object', function () { - var e1 = {}; - expect(function () { - try { - Object.isExtensible(42) - } catch (err) { - throw e1; - } - }).toThrow(e1); - }); - }); - - describe("Object.defineProperty", function () { - var obj; - - beforeEach(function() { - obj = {}; - - Object.defineProperty(obj, 'name', { - value : 'Testing', - configurable: true, - enumerable: true, - writable: true - }); - }); - - it('should return the initial value', function () { - expect(obj.hasOwnProperty('name')).toBeTruthy(); - expect(obj.name).toBe('Testing'); - }); - - it('should be setable', function () { - obj.name = 'Other'; - expect(obj.name).toBe('Other'); - }); - - it('should return the parent initial value', function () { - var child = Object.create(obj, {}); - - expect(child.name).toBe('Testing'); - expect(child.hasOwnProperty('name')).toBeFalsy(); - }); - - it('should not override the parent value', function () { - var child = Object.create(obj, {}); - - Object.defineProperty(child, 'name', { - value : 'Other' - }); - - expect(obj.name).toBe('Testing'); - expect(child.name).toBe('Other'); - }); - - it('should throw error for non object', function () { - expect(function () { - Object.defineProperty(42, 'name', {}); - }).toThrow(); - }); - }); - - describe("Object.getOwnPropertyDescriptor", function () { - it('should return undefined because the object does not own the property', function () { - var descr = Object.getOwnPropertyDescriptor({}, 'name'); - - expect(descr).toBeUndefined() - }); - - it('should return a data descriptor', function () { - var descr = Object.getOwnPropertyDescriptor({name: 'Testing'}, 'name'); - - expect(descr).not.toBeUndefined(); - expect(descr.value).toBe('Testing'); - expect(descr.writable).toBe(true); - expect(descr.enumerable).toBe(true); - expect(descr.configurable).toBe(true); - }); - - it('should return undefined because the object does not own the property', function () { - var descr = Object.getOwnPropertyDescriptor(Object.create({name: 'Testing'}, {}), 'name'); - - expect(descr).toBeUndefined() - }); - - it('should return a data descriptor', function () { - var obj = Object.create({}, { - name: { - value : 'Testing', - configurable: true, - enumerable: true, - writable: true - } - }); - - var descr = Object.getOwnPropertyDescriptor(obj, 'name'); - - expect(descr).not.toBeUndefined(); - expect(descr.value).toBe('Testing'); - expect(descr.writable).toBe(true); - expect(descr.enumerable).toBe(true); - expect(descr.configurable).toBe(true); - }); - - it('should throw error for non object', function () { - expect(function () { - Object.getOwnPropertyDescriptor(42, 'name'); - }).toThrow(); - }); - }); -}); diff --git a/dist/bower_components/es5-shim/tests/spec/s-string.js b/dist/bower_components/es5-shim/tests/spec/s-string.js deleted file mode 100644 index 9b6910d7e..000000000 --- a/dist/bower_components/es5-shim/tests/spec/s-string.js +++ /dev/null @@ -1,204 +0,0 @@ -describe('String', function() { - "use strict"; - describe("trim", function() { - var test = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFFHello, World!\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF"; - - it('trims all ES5 whitespace', function() { - expect(test.trim()).toEqual("Hello, World!"); - expect(test.trim().length).toEqual(13); - }); - }); - - describe("split", function() { - var test = "ab"; - - it('If "separator" is undefined must return Array with one String - "this" string', function() { - expect(test.split()).toEqual([test]); - expect(test.split(void 0)).toEqual([test]); - }); - - it('If "separator" is undefined and "limit" set to 0 must return Array[]', function() { - expect(test.split(void 0, 0)).toEqual([]); - }); - - describe('Tests from Steven Levithan', function () { - it("''.split() results in ['']", function () { - expect(''.split()).toEqual(['']); - }); - it("''.split(/./) results in ['']", function () { - expect(''.split(/./)).toEqual(['']); - }); - it("''.split(/.?/) results in []", function () { - expect(''.split(/.?/)).toEqual([]); - }); - it("''.split(/.??/) results in []", function () { - expect(''.split(/.??/)).toEqual([]); - }); - it("'ab'.split(/a*/) results in ['', 'b']", function () { - expect('ab'.split(/a*/)).toEqual(['', 'b']); - }); - it("'ab'.split(/a*?/) results in ['a', 'b']", function () { - expect('ab'.split(/a*?/)).toEqual(['a', 'b']); - }); - it("'ab'.split(/(?:ab)/) results in ['', '']", function () { - expect('ab'.split(/(?:ab)/)).toEqual(['', '']); - }); - it("'ab'.split(/(?:ab)*/) results in ['', '']", function () { - expect('ab'.split(/(?:ab)*/)).toEqual(['', '']); - }); - it("'ab'.split(/(?:ab)*?/) results in ['a', 'b']", function () { - expect('ab'.split(/(?:ab)*?/)).toEqual(['a', 'b']); - }); - it("'test'.split('') results in ['t', 'e', 's', 't']", function () { - expect('test'.split('')).toEqual(['t', 'e', 's', 't']); - }); - it("'test'.split() results in ['test']", function () { - expect('test'.split()).toEqual(['test']); - }); - it("'111'.split(1) results in ['', '', '', '']", function () { - expect('111'.split(1)).toEqual(['', '', '', '']); - }); - it("'test'.split(/(?:)/, 2) results in ['t', 'e']", function () { - expect('test'.split(/(?:)/, 2)).toEqual(['t', 'e']); - }); - it("'test'.split(/(?:)/, -1) results in ['t', 'e', 's', 't']", function () { - expect('test'.split(/(?:)/, -1)).toEqual(['t', 'e', 's', 't']); - }); - it("'test'.split(/(?:)/, undefined) results in ['t', 'e', 's', 't']", function () { - expect('test'.split(/(?:)/, undefined)).toEqual(['t', 'e', 's', 't']); - }); - it("'test'.split(/(?:)/, null) results in []", function () { - expect('test'.split(/(?:)/, null)).toEqual([]); - }); - it("'test'.split(/(?:)/, NaN) results in []", function () { - expect('test'.split(/(?:)/, NaN)).toEqual([]); - }); - it("'test'.split(/(?:)/, true) results in ['t']", function () { - expect('test'.split(/(?:)/, true)).toEqual(['t']); - }); - it("'test'.split(/(?:)/, '2') results in ['t', 'e']", function () { - expect('test'.split(/(?:)/, '2')).toEqual(['t', 'e']); - }); - it("'test'.split(/(?:)/, 'two') results in []", function () { - expect('test'.split(/(?:)/, 'two')).toEqual([]); - }); - it("'a'.split(/-/) results in ['a']", function () { - expect('a'.split(/-/)).toEqual(['a']); - }); - it("'a'.split(/-?/) results in ['a']", function () { - expect('a'.split(/-?/)).toEqual(['a']); - }); - it("'a'.split(/-??/) results in ['a']", function () { - expect('a'.split(/-??/)).toEqual(['a']); - }); - it("'a'.split(/a/) results in ['', '']", function () { - expect('a'.split(/a/)).toEqual(['', '']); - }); - it("'a'.split(/a?/) results in ['', '']", function () { - expect('a'.split(/a?/)).toEqual(['', '']); - }); - it("'a'.split(/a??/) results in ['a']", function () { - expect('a'.split(/a??/)).toEqual(['a']); - }); - it("'ab'.split(/-/) results in ['ab']", function () { - expect('ab'.split(/-/)).toEqual(['ab']); - }); - it("'ab'.split(/-?/) results in ['a', 'b']", function () { - expect('ab'.split(/-?/)).toEqual(['a', 'b']); - }); - it("'ab'.split(/-??/) results in ['a', 'b']", function () { - expect('ab'.split(/-??/)).toEqual(['a', 'b']); - }); - it("'a-b'.split(/-/) results in ['a', 'b']", function () { - expect('a-b'.split(/-/)).toEqual(['a', 'b']); - }); - it("'a-b'.split(/-?/) results in ['a', 'b']", function () { - expect('a-b'.split(/-?/)).toEqual(['a', 'b']); - }); - it("'a-b'.split(/-??/) results in ['a', '-', 'b']", function () { - expect('a-b'.split(/-??/)).toEqual(['a', '-', 'b']); - }); - it("'a--b'.split(/-/) results in ['a', '', 'b']", function () { - expect('a--b'.split(/-/)).toEqual(['a', '', 'b']); - }); - it("'a--b'.split(/-?/) results in ['a', '', 'b']", function () { - expect('a--b'.split(/-?/)).toEqual(['a', '', 'b']); - }); - it("'a--b'.split(/-??/) results in ['a', '-', '-', 'b']", function () { - expect('a--b'.split(/-??/)).toEqual(['a', '-', '-', 'b']); - }); - it("''.split(/()()/) results in []", function () { - expect(''.split(/()()/)).toEqual([]); - }); - it("'.'.split(/()()/) results in ['.']", function () { - expect('.'.split(/()()/)).toEqual(['.']); - }); - it("'.'.split(/(.?)(.?)/) results in ['', '.', '', '']", function () { - expect('.'.split(/(.?)(.?)/)).toEqual(['', '.', '', '']); - }); - it("'.'.split(/(.??)(.??)/) results in ['.']", function () { - expect('.'.split(/(.??)(.??)/)).toEqual(['.']); - }); - it("'.'.split(/(.)?(.)?/) results in ['', '.', undefined, '']", function () { - expect('.'.split(/(.)?(.)?/)).toEqual(['', '.', undefined, '']); - }); - it("'Aboldandcoded'.split(/<(\\/)?([^<>]+)>/) results in ['A', undefined, 'B', 'bold', '/', 'B', 'and', undefined, 'CODE', 'coded', '/', 'CODE', '']", function () { - expect('Aboldandcoded'.split(/<(\/)?([^<>]+)>/)).toEqual(['A', undefined, 'B', 'bold', '/', 'B', 'and', undefined, 'CODE', 'coded', '/', 'CODE', '']); - }); - it("'tesst'.split(/(s)*/) results in ['t', undefined, 'e', 's', 't']", function () { - expect('tesst'.split(/(s)*/)).toEqual(['t', undefined, 'e', 's', 't']); - }); - it("'tesst'.split(/(s)*?/) results in ['t', undefined, 'e', undefined, 's', undefined, 's', undefined, 't']", function () { - expect('tesst'.split(/(s)*?/)).toEqual(['t', undefined, 'e', undefined, 's', undefined, 's', undefined, 't']); - }); - it("'tesst'.split(/(s*)/) results in ['t', '', 'e', 'ss', 't']", function () { - expect('tesst'.split(/(s*)/)).toEqual(['t', '', 'e', 'ss', 't']); - }); - it("'tesst'.split(/(s*?)/) results in ['t', '', 'e', '', 's', '', 's', '', 't']", function () { - expect('tesst'.split(/(s*?)/)).toEqual(['t', '', 'e', '', 's', '', 's', '', 't']); - }); - it("'tesst'.split(/(?:s)*/) results in ['t', 'e', 't']", function () { - expect('tesst'.split(/(?:s)*/)).toEqual(['t', 'e', 't']); - }); - it("'tesst'.split(/(?=s+)/) results in ['te', 's', 'st']", function () { - expect('tesst'.split(/(?=s+)/)).toEqual(['te', 's', 'st']); - }); - it("'test'.split('t') results in ['', 'es', '']", function () { - expect('test'.split('t')).toEqual(['', 'es', '']); - }); - it("'test'.split('es') results in ['t', 't']", function () { - expect('test'.split('es')).toEqual(['t', 't']); - }); - it("'test'.split(/t/) results in ['', 'es', '']", function () { - expect('test'.split(/t/)).toEqual(['', 'es', '']); - }); - it("'test'.split(/es/) results in ['t', 't']", function () { - expect('test'.split(/es/)).toEqual(['t', 't']); - }); - it("'test'.split(/(t)/) results in ['', 't', 'es', 't', '']", function () { - expect('test'.split(/(t)/)).toEqual(['', 't', 'es', 't', '']); - }); - it("'test'.split(/(es)/) results in ['t', 'es', 't']", function () { - expect('test'.split(/(es)/)).toEqual(['t', 'es', 't']); - }); - it("'test'.split(/(t)(e)(s)(t)/) results in ['', 't', 'e', 's', 't', '']", function () { - expect('test'.split(/(t)(e)(s)(t)/)).toEqual(['', 't', 'e', 's', 't', '']); - }); - it("'.'.split(/(((.((.??)))))/) results in ['', '.', '.', '.', '', '', '']", function () { - expect('.'.split(/(((.((.??)))))/)).toEqual(['', '.', '.', '.', '', '', '']); - }); - it("'.'.split(/(((((.??)))))/) results in ['.']", function () { - expect('.'.split(/(((((.??)))))/)).toEqual(['.']); - }); - it("'a b c d'.split(/ /, -(Math.pow(2, 32) - 1)) results in ['a']", function () { - expect('a b c d'.split(/ /, -(Math.pow(2, 32) - 1))).toEqual(['a']); - }); - it("'a b c d'.split(/ /, Math.pow(2, 32) + 1) results in ['a']", function () { - expect('a b c d'.split(/ /, Math.pow(2, 32) + 1)).toEqual(['a']); - }); - it("'a b c d'.split(/ /, Infinity) results in []", function () { - expect('a b c d'.split(/ /, Infinity)).toEqual([]); - }); - }); - }); -}); diff --git a/dist/bower_components/font-awesome/.bower.json b/dist/bower_components/font-awesome/.bower.json deleted file mode 100644 index 7f6d0e3ec..000000000 --- a/dist/bower_components/font-awesome/.bower.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "font-awesome", - "homepage": "https://github.com/FortAwesome/Font-Awesome", - "version": "4.0.3", - "_release": "4.0.3", - "_resolution": { - "type": "version", - "tag": "v4.0.3", - "commit": "dc23a94e16a8daa3cbb3c7fa34d63e2812637b8f" - }, - "_source": "git://github.com/FortAwesome/Font-Awesome.git", - "_target": "~4.0.3", - "_originalSource": "font-awesome" -} \ No newline at end of file diff --git a/dist/bower_components/font-awesome/.gitignore b/dist/bower_components/font-awesome/.gitignore deleted file mode 100644 index 63dd5211c..000000000 --- a/dist/bower_components/font-awesome/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -*.pyc -*.egg-info -*.db -*.db.old -*.swp -*.db-journal - -.coverage -.DS_Store -.installed.cfg -_gh_pages/* - -.idea/* -.svn/* -src/website/static/* -src/website/media/* - -bin -cfcache -develop-eggs -dist -downloads -eggs -parts -tmp -.sass-cache -node_modules - -src/website/settingslocal.py -stunnel.log - -.ruby-version diff --git a/dist/bower_components/font-awesome/CONTRIBUTING.md b/dist/bower_components/font-awesome/CONTRIBUTING.md deleted file mode 100644 index cc2530cd8..000000000 --- a/dist/bower_components/font-awesome/CONTRIBUTING.md +++ /dev/null @@ -1,75 +0,0 @@ -# Contributing to Font Awesome - -Looking to contribute something to Font Awesome? **Here's how you can help.** - - - -## Reporting issues - -We only accept issues that are icon requests, bug reports, or feature requests. Bugs must be isolated and reproducible problems that we can fix within the Font Awesome core. Please read the following guidelines to ensure you are the paragon of bug reporting. - -1. **Search for existing issues.** We get a lot of duplicate issues, and you'd help us out a lot by first checking if someone else has reported the same issue. Moreover, the issue may have already been resolved with a fix available. -2. **Create an isolated and reproducible test case.** Be sure the problem exists in Font Awesome's code with a [reduced test case](http://css-tricks.com/reduced-test-cases/) that should be included in each bug report. -3. **Include a live example.** Make use of jsFiddle, jsBin, or Codepen to share your isolated test cases. -4. **Share as much information as possible.** Include operating system and version, browser and version, version of Font Awesome, etc. where appropriate. Also include steps to reproduce the bug. - - - -## Key branches - -- `master` is the latest, deployed version (not to be used for pull requests) -- `gh-pages` is the hosted docs (not to be used for pull requests) -- `*-wip` branches are the official work in progress branches for the next releases. All pull requests should be submitted against the appropriate branch - - - -## Notes on the repo - -As of v3.2.0, Font Awesome's CSS, LESS, SCSS, and documentation are all powered by Jekyll templates and built before each commit and release. -- `_config.yml` - much of the site is driven off variables from this file, including Font Awesome and Bootstrap versions -- `src/` - All edits to documentation, LESS, SCSS, and CSS should be made to files and templates in this directory -- `src/icons.yml` - all LESS, SCSS, and CSS icon definitions are driven off this single file - - - -## Pull requests - -- Submit all pull requests against the appropriate `*-wip` branch for easier merging -- Any changes to the docs must be made to the Liquid templates in the `src` directory -- CSS changes must be done in .less and .scss files first, never the compiled files -- If modifying the .less and .scss files, always recompile and commit the compiled files -- Try not to pollute your pull request with unintended changes--keep them simple and small -- Try to share which browsers your code has been tested in before submitting a pull request - - - -## Coding standards: HTML - -- Two spaces for indentation, never tabs -- Double quotes only, never single quotes -- Always use proper indentation -- Use tags and elements appropriate for an HTML5 doctype (e.g., self-closing tags) - - - -## Coding standards: CSS - -- Adhere to the [Recess CSS property order](http://markdotto.com/2011/11/29/css-property-order/) -- Multiple-line approach (one property and value per line) -- Always a space after a property's colon (.e.g, `display: block;` and not `display:block;`) -- End all lines with a semi-colon -- For multiple, comma-separated selectors, place each selector on it's own line -- Attribute selectors, like `input[type="text"]` should always wrap the attribute's value in double quotes, for consistency and safety (see this [blog post on unquoted attribute values](http://mathiasbynens.be/notes/unquoted-attribute-values) that can lead to XSS attacks) - - - -## License - -By contributing your code, you agree to license your contribution under the terms of the MIT License: -- http://opensource.org/licenses/mit-license.html - - - -## Thanks - -Thanks to Bootstrap for their wonderful CONTRIBUTING.MD doc. It was modified to create this one. diff --git a/dist/bower_components/font-awesome/Gemfile b/dist/bower_components/font-awesome/Gemfile deleted file mode 100644 index 499bcea70..000000000 --- a/dist/bower_components/font-awesome/Gemfile +++ /dev/null @@ -1,4 +0,0 @@ -source 'https://rubygems.org' - -gem 'jekyll', '~> 1.0' -gem 'debugger' diff --git a/dist/bower_components/font-awesome/Gemfile.lock b/dist/bower_components/font-awesome/Gemfile.lock deleted file mode 100644 index b677d9c0f..000000000 --- a/dist/bower_components/font-awesome/Gemfile.lock +++ /dev/null @@ -1,46 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - classifier (1.3.3) - fast-stemmer (>= 1.0.0) - colorator (0.1) - columnize (0.3.6) - commander (4.1.3) - highline (~> 1.6.11) - debugger (1.6.0) - columnize (>= 0.3.1) - debugger-linecache (~> 1.2.0) - debugger-ruby_core_source (~> 1.2.1) - debugger-linecache (1.2.0) - debugger-ruby_core_source (1.2.2) - directory_watcher (1.4.1) - fast-stemmer (1.0.2) - highline (1.6.19) - jekyll (1.0.0) - classifier (~> 1.3) - colorator (~> 0.1) - commander (~> 4.1.3) - directory_watcher (~> 1.4.1) - kramdown (~> 0.14) - liquid (~> 2.3) - maruku (~> 0.5) - pygments.rb (~> 0.4.2) - safe_yaml (~> 0.7.0) - kramdown (0.14.2) - liquid (2.5.0) - maruku (0.6.1) - syntax (>= 1.0.0) - posix-spawn (0.3.6) - pygments.rb (0.4.2) - posix-spawn (~> 0.3.6) - yajl-ruby (~> 1.1.0) - safe_yaml (0.7.1) - syntax (1.0.0) - yajl-ruby (1.1.0) - -PLATFORMS - ruby - -DEPENDENCIES - debugger - jekyll (~> 1.0) diff --git a/dist/bower_components/font-awesome/README.md b/dist/bower_components/font-awesome/README.md deleted file mode 100644 index 874d76c7e..000000000 --- a/dist/bower_components/font-awesome/README.md +++ /dev/null @@ -1,77 +0,0 @@ -#[Font Awesome v4.0.3](http://fontawesome.io) -###the iconic font designed for Bootstrap - -Font Awesome is a full suite of 369 pictographic icons for easy scalable vector graphics on websites, created and -maintained by [Dave Gandy](http://twitter.com/davegandy). Stay up to date [@fontawesome](http://twitter.com/fontawesome). - -Get started at http://fontawesome.io! - -##License -- The Font Awesome font is licensed under the SIL OFL 1.1: - - http://scripts.sil.org/OFL -- Font Awesome CSS, LESS, and SASS files are licensed under the MIT License: - - http://opensource.org/licenses/mit-license.html -- The Font Awesome documentation is licensed under the CC BY 3.0 License: - - http://creativecommons.org/licenses/by/3.0/ -- Attribution is no longer required as of Font Awesome 3.0, but much appreciated: - - `Font Awesome by Dave Gandy - http://fontawesome.io` -- Full details: http://fontawesome.io/license - -##Changelog -- v3.0.0 - all icons redesigned from scratch, optimized for Bootstrap's 14px default -- v3.0.1 - much improved rendering in webkit, various bug fixes -- v3.0.2 - much improved rendering and alignment in IE7 -- v3.1.0 - Added 54 icons, icon stacking styles, flipping and rotating icons, removed SASS support -- [v3.1.1 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=4&page=1&state=closed) -- [v3.2.0 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=3&page=1&state=closed) -- [v3.2.1 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=5&page=1&state=closed) -- [v4.0.0 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=2&page=1&state=closed) -- [v4.0.1 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=7&page=1&state=closed) -- [v4.0.2 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=8&page=1&state=closed) -- [v4.0.3 GitHub milestones](https://github.com/FortAwesome/Font-Awesome/issues?milestone=9&page=1&state=closed) - -##Versioning - -Font Awesome will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format: - -`..` - -And constructed with the following guidelines: - -* Breaking backward compatibility bumps the major (and resets the minor and patch) -* New additions, including new icons, without breaking backward compatibility bumps the minor (and resets the patch) -* Bug fixes and misc changes bumps the patch - -For more information on SemVer, please visit http://semver.org. - -##Author -- Email: dave@fontawesome.io -- Twitter: http://twitter.com/davegandy -- GitHub: https://github.com/davegandy -- Work: Lead Product Designer @ http://kyru.us - -##Component -To include as a [component](http://github.com/component/component), just run - - $ component install FortAwesome/Font-Awesome - -Or add - - "FortAwesome/Font-Awesome": "*" - -to the `dependencies` in your `component.json`. - -## Hacking on Font Awesome - -From the root of the repository, install the tools used to develop. - - $ bundle install - $ npm install - -Build the project and documentation: - - $ bundle exec jekyll build - -Or serve it on a local server on http://localhost:7998/Font-Awesome/: - - $ bundle exec jekyll serve diff --git a/dist/bower_components/font-awesome/_config.yml b/dist/bower_components/font-awesome/_config.yml deleted file mode 100644 index d68d5faa3..000000000 --- a/dist/bower_components/font-awesome/_config.yml +++ /dev/null @@ -1,58 +0,0 @@ -safe: false -port: 7998 -baseurl: /Font-Awesome/ # Where GitHub serves the project up from -url: http://localhost:7998 - -source: src -destination: _gh_pages -plugins: src/_plugins - -pygments: true -permalink: pretty - -# ensures SCSS files are compiled -include: [_bordered-pulled.scss, _core.scss, _fixed-width.scss, _icons.scss, _larger.scss, _list.scss, _mixins.scss, _path.scss, _rotated-flipped.scss, _spinning.scss, _stacked.scss, _variables.scss] - -# used in building icon pages -icon_meta: src/icons.yml -icon_layout: icon.html # Relative to _layouts directory -icon_destination: icon # Relative to destination - -fontawesome: - version: 4.0.3 - minor_version: 4.0 - url: http://fontawesome.io - legacy_url: http://fortawesome.github.com/Font-Awesome/ - blog_url: http://blog.fontawesome.io - twitter: fontawesome - tagline: The iconic font designed for Bootstrap - css_prefix: fa - author: - name: Dave Gandy - email: dave@fontawesome.io - twitter: davegandy - work: - name: Kyruus - url: http://kyruus.com - title: Lead Product Designer - github: - url: https://github.com/FortAwesome/Font-Awesome - project: Font-Awesome - org: FortAwesome - license: - font: - version: SIL OFL 1.1 - url: http://scripts.sil.org/OFL - code: - version: MIT License - url: http://opensource.org/licenses/mit-license.html - documentation: - version: CC BY 3.0 - url: http://creativecommons.org/licenses/by/3.0/ - -bootstrap: - version: 3.0.0 - url: http://getbootstrap.com - -jquery: - version: 1.10.2 diff --git a/dist/bower_components/font-awesome/component.json b/dist/bower_components/font-awesome/component.json deleted file mode 100644 index 4625d0941..000000000 --- a/dist/bower_components/font-awesome/component.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "Font-Awesome", - "repo": "FortAwesome/Font-Awesome", - "description": "Font Awesome", - "version": "4.0.3", - "keywords": [], - "dependencies": {}, - "development": {}, - "license": "SIL, MIT, CC BY 3.0", - "styles": [ - "css/font-awesome.css" - ], - "fonts": [ - "fonts/fontawesome-webfont.eot", - "fonts/fontawesome-webfont.svg", - "fonts/fontawesome-webfont.ttf", - "fonts/fontawesome-webfont.woff", - "fonts/FontAwesome.otf" - ] -} diff --git a/dist/bower_components/font-awesome/composer.json b/dist/bower_components/font-awesome/composer.json deleted file mode 100644 index 49b9b3069..000000000 --- a/dist/bower_components/font-awesome/composer.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "fortawesome/font-awesome", - "description": "The iconic font designed for Bootstrap", - "keywords": ["font", "awesome", "fontawesome", "icon", "font", "bootstrap"], - "homepage": "http://fontawesome.io/", - "authors": [ - { - "name": "Dave Gandy", - "email": "dave@fontawesome.io", - "role": "Developer", - "homepage": "http://twitter.com/davegandy" - } - ], - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, - "license": [ - "OFL-1.1", - "MIT" - ], - "require-dev": { - "jekyll": "1.0.2", - "lessc": "1.4.2" - } -} diff --git a/dist/bower_components/font-awesome/css/font-awesome.css b/dist/bower_components/font-awesome/css/font-awesome.css deleted file mode 100644 index 048cff973..000000000 --- a/dist/bower_components/font-awesome/css/font-awesome.css +++ /dev/null @@ -1,1338 +0,0 @@ -/*! - * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -/* FONT PATH - * -------------------------- */ -@font-face { - font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.0.3'); - src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg'); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font-family: FontAwesome; - font-style: normal; - font-weight: normal; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -/* makes the font 33% larger relative to the icon container */ -.fa-lg { - font-size: 1.3333333333333333em; - line-height: 0.75em; - vertical-align: -15%; -} -.fa-2x { - font-size: 2em; -} -.fa-3x { - font-size: 3em; -} -.fa-4x { - font-size: 4em; -} -.fa-5x { - font-size: 5em; -} -.fa-fw { - width: 1.2857142857142858em; - text-align: center; -} -.fa-ul { - padding-left: 0; - margin-left: 2.142857142857143em; - list-style-type: none; -} -.fa-ul > li { - position: relative; -} -.fa-li { - position: absolute; - left: -2.142857142857143em; - width: 2.142857142857143em; - top: 0.14285714285714285em; - text-align: center; -} -.fa-li.fa-lg { - left: -1.8571428571428572em; -} -.fa-border { - padding: .2em .25em .15em; - border: solid 0.08em #eeeeee; - border-radius: .1em; -} -.pull-right { - float: right; -} -.pull-left { - float: left; -} -.fa.pull-left { - margin-right: .3em; -} -.fa.pull-right { - margin-left: .3em; -} -.fa-spin { - -webkit-animation: spin 2s infinite linear; - -moz-animation: spin 2s infinite linear; - -o-animation: spin 2s infinite linear; - animation: spin 2s infinite linear; -} -@-moz-keyframes spin { - 0% { - -moz-transform: rotate(0deg); - } - 100% { - -moz-transform: rotate(359deg); - } -} -@-webkit-keyframes spin { - 0% { - -webkit-transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - } -} -@-o-keyframes spin { - 0% { - -o-transform: rotate(0deg); - } - 100% { - -o-transform: rotate(359deg); - } -} -@-ms-keyframes spin { - 0% { - -ms-transform: rotate(0deg); - } - 100% { - -ms-transform: rotate(359deg); - } -} -@keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(359deg); - } -} -.fa-rotate-90 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); - -webkit-transform: rotate(90deg); - -moz-transform: rotate(90deg); - -ms-transform: rotate(90deg); - -o-transform: rotate(90deg); - transform: rotate(90deg); -} -.fa-rotate-180 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); - -webkit-transform: rotate(180deg); - -moz-transform: rotate(180deg); - -ms-transform: rotate(180deg); - -o-transform: rotate(180deg); - transform: rotate(180deg); -} -.fa-rotate-270 { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); - -webkit-transform: rotate(270deg); - -moz-transform: rotate(270deg); - -ms-transform: rotate(270deg); - -o-transform: rotate(270deg); - transform: rotate(270deg); -} -.fa-flip-horizontal { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); - -webkit-transform: scale(-1, 1); - -moz-transform: scale(-1, 1); - -ms-transform: scale(-1, 1); - -o-transform: scale(-1, 1); - transform: scale(-1, 1); -} -.fa-flip-vertical { - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); - -webkit-transform: scale(1, -1); - -moz-transform: scale(1, -1); - -ms-transform: scale(1, -1); - -o-transform: scale(1, -1); - transform: scale(1, -1); -} -.fa-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: middle; -} -.fa-stack-1x, -.fa-stack-2x { - position: absolute; - left: 0; - width: 100%; - text-align: center; -} -.fa-stack-1x { - line-height: inherit; -} -.fa-stack-2x { - font-size: 2em; -} -.fa-inverse { - color: #ffffff; -} -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen - readers do not read off random characters that represent icons */ -.fa-glass:before { - content: "\f000"; -} -.fa-music:before { - content: "\f001"; -} -.fa-search:before { - content: "\f002"; -} -.fa-envelope-o:before { - content: "\f003"; -} -.fa-heart:before { - content: "\f004"; -} -.fa-star:before { - content: "\f005"; -} -.fa-star-o:before { - content: "\f006"; -} -.fa-user:before { - content: "\f007"; -} -.fa-film:before { - content: "\f008"; -} -.fa-th-large:before { - content: "\f009"; -} -.fa-th:before { - content: "\f00a"; -} -.fa-th-list:before { - content: "\f00b"; -} -.fa-check:before { - content: "\f00c"; -} -.fa-times:before { - content: "\f00d"; -} -.fa-search-plus:before { - content: "\f00e"; -} -.fa-search-minus:before { - content: "\f010"; -} -.fa-power-off:before { - content: "\f011"; -} -.fa-signal:before { - content: "\f012"; -} -.fa-gear:before, -.fa-cog:before { - content: "\f013"; -} -.fa-trash-o:before { - content: "\f014"; -} -.fa-home:before { - content: "\f015"; -} -.fa-file-o:before { - content: "\f016"; -} -.fa-clock-o:before { - content: "\f017"; -} -.fa-road:before { - content: "\f018"; -} -.fa-download:before { - content: "\f019"; -} -.fa-arrow-circle-o-down:before { - content: "\f01a"; -} -.fa-arrow-circle-o-up:before { - content: "\f01b"; -} -.fa-inbox:before { - content: "\f01c"; -} -.fa-play-circle-o:before { - content: "\f01d"; -} -.fa-rotate-right:before, -.fa-repeat:before { - content: "\f01e"; -} -.fa-refresh:before { - content: "\f021"; -} -.fa-list-alt:before { - content: "\f022"; -} -.fa-lock:before { - content: "\f023"; -} -.fa-flag:before { - content: "\f024"; -} -.fa-headphones:before { - content: "\f025"; -} -.fa-volume-off:before { - content: "\f026"; -} -.fa-volume-down:before { - content: "\f027"; -} -.fa-volume-up:before { - content: "\f028"; -} -.fa-qrcode:before { - content: "\f029"; -} -.fa-barcode:before { - content: "\f02a"; -} -.fa-tag:before { - content: "\f02b"; -} -.fa-tags:before { - content: "\f02c"; -} -.fa-book:before { - content: "\f02d"; -} -.fa-bookmark:before { - content: "\f02e"; -} -.fa-print:before { - content: "\f02f"; -} -.fa-camera:before { - content: "\f030"; -} -.fa-font:before { - content: "\f031"; -} -.fa-bold:before { - content: "\f032"; -} -.fa-italic:before { - content: "\f033"; -} -.fa-text-height:before { - content: "\f034"; -} -.fa-text-width:before { - content: "\f035"; -} -.fa-align-left:before { - content: "\f036"; -} -.fa-align-center:before { - content: "\f037"; -} -.fa-align-right:before { - content: "\f038"; -} -.fa-align-justify:before { - content: "\f039"; -} -.fa-list:before { - content: "\f03a"; -} -.fa-dedent:before, -.fa-outdent:before { - content: "\f03b"; -} -.fa-indent:before { - content: "\f03c"; -} -.fa-video-camera:before { - content: "\f03d"; -} -.fa-picture-o:before { - content: "\f03e"; -} -.fa-pencil:before { - content: "\f040"; -} -.fa-map-marker:before { - content: "\f041"; -} -.fa-adjust:before { - content: "\f042"; -} -.fa-tint:before { - content: "\f043"; -} -.fa-edit:before, -.fa-pencil-square-o:before { - content: "\f044"; -} -.fa-share-square-o:before { - content: "\f045"; -} -.fa-check-square-o:before { - content: "\f046"; -} -.fa-arrows:before { - content: "\f047"; -} -.fa-step-backward:before { - content: "\f048"; -} -.fa-fast-backward:before { - content: "\f049"; -} -.fa-backward:before { - content: "\f04a"; -} -.fa-play:before { - content: "\f04b"; -} -.fa-pause:before { - content: "\f04c"; -} -.fa-stop:before { - content: "\f04d"; -} -.fa-forward:before { - content: "\f04e"; -} -.fa-fast-forward:before { - content: "\f050"; -} -.fa-step-forward:before { - content: "\f051"; -} -.fa-eject:before { - content: "\f052"; -} -.fa-chevron-left:before { - content: "\f053"; -} -.fa-chevron-right:before { - content: "\f054"; -} -.fa-plus-circle:before { - content: "\f055"; -} -.fa-minus-circle:before { - content: "\f056"; -} -.fa-times-circle:before { - content: "\f057"; -} -.fa-check-circle:before { - content: "\f058"; -} -.fa-question-circle:before { - content: "\f059"; -} -.fa-info-circle:before { - content: "\f05a"; -} -.fa-crosshairs:before { - content: "\f05b"; -} -.fa-times-circle-o:before { - content: "\f05c"; -} -.fa-check-circle-o:before { - content: "\f05d"; -} -.fa-ban:before { - content: "\f05e"; -} -.fa-arrow-left:before { - content: "\f060"; -} -.fa-arrow-right:before { - content: "\f061"; -} -.fa-arrow-up:before { - content: "\f062"; -} -.fa-arrow-down:before { - content: "\f063"; -} -.fa-mail-forward:before, -.fa-share:before { - content: "\f064"; -} -.fa-expand:before { - content: "\f065"; -} -.fa-compress:before { - content: "\f066"; -} -.fa-plus:before { - content: "\f067"; -} -.fa-minus:before { - content: "\f068"; -} -.fa-asterisk:before { - content: "\f069"; -} -.fa-exclamation-circle:before { - content: "\f06a"; -} -.fa-gift:before { - content: "\f06b"; -} -.fa-leaf:before { - content: "\f06c"; -} -.fa-fire:before { - content: "\f06d"; -} -.fa-eye:before { - content: "\f06e"; -} -.fa-eye-slash:before { - content: "\f070"; -} -.fa-warning:before, -.fa-exclamation-triangle:before { - content: "\f071"; -} -.fa-plane:before { - content: "\f072"; -} -.fa-calendar:before { - content: "\f073"; -} -.fa-random:before { - content: "\f074"; -} -.fa-comment:before { - content: "\f075"; -} -.fa-magnet:before { - content: "\f076"; -} -.fa-chevron-up:before { - content: "\f077"; -} -.fa-chevron-down:before { - content: "\f078"; -} -.fa-retweet:before { - content: "\f079"; -} -.fa-shopping-cart:before { - content: "\f07a"; -} -.fa-folder:before { - content: "\f07b"; -} -.fa-folder-open:before { - content: "\f07c"; -} -.fa-arrows-v:before { - content: "\f07d"; -} -.fa-arrows-h:before { - content: "\f07e"; -} -.fa-bar-chart-o:before { - content: "\f080"; -} -.fa-twitter-square:before { - content: "\f081"; -} -.fa-facebook-square:before { - content: "\f082"; -} -.fa-camera-retro:before { - content: "\f083"; -} -.fa-key:before { - content: "\f084"; -} -.fa-gears:before, -.fa-cogs:before { - content: "\f085"; -} -.fa-comments:before { - content: "\f086"; -} -.fa-thumbs-o-up:before { - content: "\f087"; -} -.fa-thumbs-o-down:before { - content: "\f088"; -} -.fa-star-half:before { - content: "\f089"; -} -.fa-heart-o:before { - content: "\f08a"; -} -.fa-sign-out:before { - content: "\f08b"; -} -.fa-linkedin-square:before { - content: "\f08c"; -} -.fa-thumb-tack:before { - content: "\f08d"; -} -.fa-external-link:before { - content: "\f08e"; -} -.fa-sign-in:before { - content: "\f090"; -} -.fa-trophy:before { - content: "\f091"; -} -.fa-github-square:before { - content: "\f092"; -} -.fa-upload:before { - content: "\f093"; -} -.fa-lemon-o:before { - content: "\f094"; -} -.fa-phone:before { - content: "\f095"; -} -.fa-square-o:before { - content: "\f096"; -} -.fa-bookmark-o:before { - content: "\f097"; -} -.fa-phone-square:before { - content: "\f098"; -} -.fa-twitter:before { - content: "\f099"; -} -.fa-facebook:before { - content: "\f09a"; -} -.fa-github:before { - content: "\f09b"; -} -.fa-unlock:before { - content: "\f09c"; -} -.fa-credit-card:before { - content: "\f09d"; -} -.fa-rss:before { - content: "\f09e"; -} -.fa-hdd-o:before { - content: "\f0a0"; -} -.fa-bullhorn:before { - content: "\f0a1"; -} -.fa-bell:before { - content: "\f0f3"; -} -.fa-certificate:before { - content: "\f0a3"; -} -.fa-hand-o-right:before { - content: "\f0a4"; -} -.fa-hand-o-left:before { - content: "\f0a5"; -} -.fa-hand-o-up:before { - content: "\f0a6"; -} -.fa-hand-o-down:before { - content: "\f0a7"; -} -.fa-arrow-circle-left:before { - content: "\f0a8"; -} -.fa-arrow-circle-right:before { - content: "\f0a9"; -} -.fa-arrow-circle-up:before { - content: "\f0aa"; -} -.fa-arrow-circle-down:before { - content: "\f0ab"; -} -.fa-globe:before { - content: "\f0ac"; -} -.fa-wrench:before { - content: "\f0ad"; -} -.fa-tasks:before { - content: "\f0ae"; -} -.fa-filter:before { - content: "\f0b0"; -} -.fa-briefcase:before { - content: "\f0b1"; -} -.fa-arrows-alt:before { - content: "\f0b2"; -} -.fa-group:before, -.fa-users:before { - content: "\f0c0"; -} -.fa-chain:before, -.fa-link:before { - content: "\f0c1"; -} -.fa-cloud:before { - content: "\f0c2"; -} -.fa-flask:before { - content: "\f0c3"; -} -.fa-cut:before, -.fa-scissors:before { - content: "\f0c4"; -} -.fa-copy:before, -.fa-files-o:before { - content: "\f0c5"; -} -.fa-paperclip:before { - content: "\f0c6"; -} -.fa-save:before, -.fa-floppy-o:before { - content: "\f0c7"; -} -.fa-square:before { - content: "\f0c8"; -} -.fa-bars:before { - content: "\f0c9"; -} -.fa-list-ul:before { - content: "\f0ca"; -} -.fa-list-ol:before { - content: "\f0cb"; -} -.fa-strikethrough:before { - content: "\f0cc"; -} -.fa-underline:before { - content: "\f0cd"; -} -.fa-table:before { - content: "\f0ce"; -} -.fa-magic:before { - content: "\f0d0"; -} -.fa-truck:before { - content: "\f0d1"; -} -.fa-pinterest:before { - content: "\f0d2"; -} -.fa-pinterest-square:before { - content: "\f0d3"; -} -.fa-google-plus-square:before { - content: "\f0d4"; -} -.fa-google-plus:before { - content: "\f0d5"; -} -.fa-money:before { - content: "\f0d6"; -} -.fa-caret-down:before { - content: "\f0d7"; -} -.fa-caret-up:before { - content: "\f0d8"; -} -.fa-caret-left:before { - content: "\f0d9"; -} -.fa-caret-right:before { - content: "\f0da"; -} -.fa-columns:before { - content: "\f0db"; -} -.fa-unsorted:before, -.fa-sort:before { - content: "\f0dc"; -} -.fa-sort-down:before, -.fa-sort-asc:before { - content: "\f0dd"; -} -.fa-sort-up:before, -.fa-sort-desc:before { - content: "\f0de"; -} -.fa-envelope:before { - content: "\f0e0"; -} -.fa-linkedin:before { - content: "\f0e1"; -} -.fa-rotate-left:before, -.fa-undo:before { - content: "\f0e2"; -} -.fa-legal:before, -.fa-gavel:before { - content: "\f0e3"; -} -.fa-dashboard:before, -.fa-tachometer:before { - content: "\f0e4"; -} -.fa-comment-o:before { - content: "\f0e5"; -} -.fa-comments-o:before { - content: "\f0e6"; -} -.fa-flash:before, -.fa-bolt:before { - content: "\f0e7"; -} -.fa-sitemap:before { - content: "\f0e8"; -} -.fa-umbrella:before { - content: "\f0e9"; -} -.fa-paste:before, -.fa-clipboard:before { - content: "\f0ea"; -} -.fa-lightbulb-o:before { - content: "\f0eb"; -} -.fa-exchange:before { - content: "\f0ec"; -} -.fa-cloud-download:before { - content: "\f0ed"; -} -.fa-cloud-upload:before { - content: "\f0ee"; -} -.fa-user-md:before { - content: "\f0f0"; -} -.fa-stethoscope:before { - content: "\f0f1"; -} -.fa-suitcase:before { - content: "\f0f2"; -} -.fa-bell-o:before { - content: "\f0a2"; -} -.fa-coffee:before { - content: "\f0f4"; -} -.fa-cutlery:before { - content: "\f0f5"; -} -.fa-file-text-o:before { - content: "\f0f6"; -} -.fa-building-o:before { - content: "\f0f7"; -} -.fa-hospital-o:before { - content: "\f0f8"; -} -.fa-ambulance:before { - content: "\f0f9"; -} -.fa-medkit:before { - content: "\f0fa"; -} -.fa-fighter-jet:before { - content: "\f0fb"; -} -.fa-beer:before { - content: "\f0fc"; -} -.fa-h-square:before { - content: "\f0fd"; -} -.fa-plus-square:before { - content: "\f0fe"; -} -.fa-angle-double-left:before { - content: "\f100"; -} -.fa-angle-double-right:before { - content: "\f101"; -} -.fa-angle-double-up:before { - content: "\f102"; -} -.fa-angle-double-down:before { - content: "\f103"; -} -.fa-angle-left:before { - content: "\f104"; -} -.fa-angle-right:before { - content: "\f105"; -} -.fa-angle-up:before { - content: "\f106"; -} -.fa-angle-down:before { - content: "\f107"; -} -.fa-desktop:before { - content: "\f108"; -} -.fa-laptop:before { - content: "\f109"; -} -.fa-tablet:before { - content: "\f10a"; -} -.fa-mobile-phone:before, -.fa-mobile:before { - content: "\f10b"; -} -.fa-circle-o:before { - content: "\f10c"; -} -.fa-quote-left:before { - content: "\f10d"; -} -.fa-quote-right:before { - content: "\f10e"; -} -.fa-spinner:before { - content: "\f110"; -} -.fa-circle:before { - content: "\f111"; -} -.fa-mail-reply:before, -.fa-reply:before { - content: "\f112"; -} -.fa-github-alt:before { - content: "\f113"; -} -.fa-folder-o:before { - content: "\f114"; -} -.fa-folder-open-o:before { - content: "\f115"; -} -.fa-smile-o:before { - content: "\f118"; -} -.fa-frown-o:before { - content: "\f119"; -} -.fa-meh-o:before { - content: "\f11a"; -} -.fa-gamepad:before { - content: "\f11b"; -} -.fa-keyboard-o:before { - content: "\f11c"; -} -.fa-flag-o:before { - content: "\f11d"; -} -.fa-flag-checkered:before { - content: "\f11e"; -} -.fa-terminal:before { - content: "\f120"; -} -.fa-code:before { - content: "\f121"; -} -.fa-reply-all:before { - content: "\f122"; -} -.fa-mail-reply-all:before { - content: "\f122"; -} -.fa-star-half-empty:before, -.fa-star-half-full:before, -.fa-star-half-o:before { - content: "\f123"; -} -.fa-location-arrow:before { - content: "\f124"; -} -.fa-crop:before { - content: "\f125"; -} -.fa-code-fork:before { - content: "\f126"; -} -.fa-unlink:before, -.fa-chain-broken:before { - content: "\f127"; -} -.fa-question:before { - content: "\f128"; -} -.fa-info:before { - content: "\f129"; -} -.fa-exclamation:before { - content: "\f12a"; -} -.fa-superscript:before { - content: "\f12b"; -} -.fa-subscript:before { - content: "\f12c"; -} -.fa-eraser:before { - content: "\f12d"; -} -.fa-puzzle-piece:before { - content: "\f12e"; -} -.fa-microphone:before { - content: "\f130"; -} -.fa-microphone-slash:before { - content: "\f131"; -} -.fa-shield:before { - content: "\f132"; -} -.fa-calendar-o:before { - content: "\f133"; -} -.fa-fire-extinguisher:before { - content: "\f134"; -} -.fa-rocket:before { - content: "\f135"; -} -.fa-maxcdn:before { - content: "\f136"; -} -.fa-chevron-circle-left:before { - content: "\f137"; -} -.fa-chevron-circle-right:before { - content: "\f138"; -} -.fa-chevron-circle-up:before { - content: "\f139"; -} -.fa-chevron-circle-down:before { - content: "\f13a"; -} -.fa-html5:before { - content: "\f13b"; -} -.fa-css3:before { - content: "\f13c"; -} -.fa-anchor:before { - content: "\f13d"; -} -.fa-unlock-alt:before { - content: "\f13e"; -} -.fa-bullseye:before { - content: "\f140"; -} -.fa-ellipsis-h:before { - content: "\f141"; -} -.fa-ellipsis-v:before { - content: "\f142"; -} -.fa-rss-square:before { - content: "\f143"; -} -.fa-play-circle:before { - content: "\f144"; -} -.fa-ticket:before { - content: "\f145"; -} -.fa-minus-square:before { - content: "\f146"; -} -.fa-minus-square-o:before { - content: "\f147"; -} -.fa-level-up:before { - content: "\f148"; -} -.fa-level-down:before { - content: "\f149"; -} -.fa-check-square:before { - content: "\f14a"; -} -.fa-pencil-square:before { - content: "\f14b"; -} -.fa-external-link-square:before { - content: "\f14c"; -} -.fa-share-square:before { - content: "\f14d"; -} -.fa-compass:before { - content: "\f14e"; -} -.fa-toggle-down:before, -.fa-caret-square-o-down:before { - content: "\f150"; -} -.fa-toggle-up:before, -.fa-caret-square-o-up:before { - content: "\f151"; -} -.fa-toggle-right:before, -.fa-caret-square-o-right:before { - content: "\f152"; -} -.fa-euro:before, -.fa-eur:before { - content: "\f153"; -} -.fa-gbp:before { - content: "\f154"; -} -.fa-dollar:before, -.fa-usd:before { - content: "\f155"; -} -.fa-rupee:before, -.fa-inr:before { - content: "\f156"; -} -.fa-cny:before, -.fa-rmb:before, -.fa-yen:before, -.fa-jpy:before { - content: "\f157"; -} -.fa-ruble:before, -.fa-rouble:before, -.fa-rub:before { - content: "\f158"; -} -.fa-won:before, -.fa-krw:before { - content: "\f159"; -} -.fa-bitcoin:before, -.fa-btc:before { - content: "\f15a"; -} -.fa-file:before { - content: "\f15b"; -} -.fa-file-text:before { - content: "\f15c"; -} -.fa-sort-alpha-asc:before { - content: "\f15d"; -} -.fa-sort-alpha-desc:before { - content: "\f15e"; -} -.fa-sort-amount-asc:before { - content: "\f160"; -} -.fa-sort-amount-desc:before { - content: "\f161"; -} -.fa-sort-numeric-asc:before { - content: "\f162"; -} -.fa-sort-numeric-desc:before { - content: "\f163"; -} -.fa-thumbs-up:before { - content: "\f164"; -} -.fa-thumbs-down:before { - content: "\f165"; -} -.fa-youtube-square:before { - content: "\f166"; -} -.fa-youtube:before { - content: "\f167"; -} -.fa-xing:before { - content: "\f168"; -} -.fa-xing-square:before { - content: "\f169"; -} -.fa-youtube-play:before { - content: "\f16a"; -} -.fa-dropbox:before { - content: "\f16b"; -} -.fa-stack-overflow:before { - content: "\f16c"; -} -.fa-instagram:before { - content: "\f16d"; -} -.fa-flickr:before { - content: "\f16e"; -} -.fa-adn:before { - content: "\f170"; -} -.fa-bitbucket:before { - content: "\f171"; -} -.fa-bitbucket-square:before { - content: "\f172"; -} -.fa-tumblr:before { - content: "\f173"; -} -.fa-tumblr-square:before { - content: "\f174"; -} -.fa-long-arrow-down:before { - content: "\f175"; -} -.fa-long-arrow-up:before { - content: "\f176"; -} -.fa-long-arrow-left:before { - content: "\f177"; -} -.fa-long-arrow-right:before { - content: "\f178"; -} -.fa-apple:before { - content: "\f179"; -} -.fa-windows:before { - content: "\f17a"; -} -.fa-android:before { - content: "\f17b"; -} -.fa-linux:before { - content: "\f17c"; -} -.fa-dribbble:before { - content: "\f17d"; -} -.fa-skype:before { - content: "\f17e"; -} -.fa-foursquare:before { - content: "\f180"; -} -.fa-trello:before { - content: "\f181"; -} -.fa-female:before { - content: "\f182"; -} -.fa-male:before { - content: "\f183"; -} -.fa-gittip:before { - content: "\f184"; -} -.fa-sun-o:before { - content: "\f185"; -} -.fa-moon-o:before { - content: "\f186"; -} -.fa-archive:before { - content: "\f187"; -} -.fa-bug:before { - content: "\f188"; -} -.fa-vk:before { - content: "\f189"; -} -.fa-weibo:before { - content: "\f18a"; -} -.fa-renren:before { - content: "\f18b"; -} -.fa-pagelines:before { - content: "\f18c"; -} -.fa-stack-exchange:before { - content: "\f18d"; -} -.fa-arrow-circle-o-right:before { - content: "\f18e"; -} -.fa-arrow-circle-o-left:before { - content: "\f190"; -} -.fa-toggle-left:before, -.fa-caret-square-o-left:before { - content: "\f191"; -} -.fa-dot-circle-o:before { - content: "\f192"; -} -.fa-wheelchair:before { - content: "\f193"; -} -.fa-vimeo-square:before { - content: "\f194"; -} -.fa-turkish-lira:before, -.fa-try:before { - content: "\f195"; -} -.fa-plus-square-o:before { - content: "\f196"; -} diff --git a/dist/bower_components/font-awesome/css/font-awesome.min.css b/dist/bower_components/font-awesome/css/font-awesome.min.css deleted file mode 100644 index 449d6ac55..000000000 --- a/dist/bower_components/font-awesome/css/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.0.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"} \ No newline at end of file diff --git a/dist/bower_components/font-awesome/fonts/FontAwesome.otf b/dist/bower_components/font-awesome/fonts/FontAwesome.otf deleted file mode 100644 index 8b0f54e47e1d356dcf1496942a50e228e0f1ee14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62856 zcmcfp2Y3_5)&LBzEbU6(wGF`%u_do$I-wUs=poc3^xzP>t859|l91%ydy%{4ZewH9 zLNU#OK%5)jlp7M#adH#VlN(Y~MSVYG)7F`Dsts8mQIv>+ztD)dFw+9OVG%`1 zdML`ns?&x=Qnp|IfM+dm&(}ePcdqmf37+Ghm#p%f+FVKQ2*chjkzF#ZB~9w-bef!xGBr6D7h{6UGOP@t%*!8rhr zqTX&D_txFJckW8F88SgJDOYWQiq1}9HpST zU`<34PZ)C!_3}_&M2)6kC53tq%16Wv<;B!kk^fL$a$g&o8ZTNrRL|U3FQqy}Aw%^t z%FjbIl=r0M9>Z`rYKq77t>{++@-k0@oM~*1+}p2(7`Q4V*n=HYq=vsI?g5v}-nP z3|{}}ibb1(*R0;YdDD}@+q7nj-e?F6nlWp}oWMD=X3yOms||yGW^I(#9B4HL0`>*2 zG{Pq6qjlCmi#Eba+D94TAv}p9V_D5%k=nR0b4*~E)oRv<#|upiMk~z0GGmR=Yz-V5 ze^pq5HgIj2Au?HKwVD>qoJsnJx#u=RZ=|+Tk5lVmJ2z1#N=q3aw}vu8YK7c-N>4=y zwHEjdq-Iky;2wVdD3u7c7HAy@>636rQ}I+R6-Jq%%_eFi6$}s_rB+ajpcD*stEugP zo136*FtrWZo1wQ}7%h+r0@$R$MYWppE&yKBVk^ODoieQIXI-PMCWPv3^jr9p7*cDDu9q6%xx{?3;;b@n3omixrmwx*YNmZf9p3xm@i;8 zp?TpJjUB@J0D^@;Vq@WEgcj}}s2gf=U*-SLs=qz||El20$!O-RlsfnS_J9)6lK^rf z@F|+|fem;DctSVzuQ6lCs>g=*`}C{(m-TP#-`gM6ukSbXXY`l%AL#GuKiB_u|L6U` z^xwJVb4z_|(yht2X53nKYvZlGw+y#3Zk69U@CS95u-8E9*x%q${UiIw^e^w<+#lK> z-M_Ej)SuN~+27uOroXrU-Tp88`)^UVM&1epcn{s0b!+*p&9_2tnQmp>swD94ennAt zcir7`_tDR9d~W}I%Sf-0+(^%nvXRn}u#+RjBRxinMp7g0j<_@8_K4p{{5Im&i2f13 zj`+pr(-A+9_-Vw=5kHRjVZ`?%z8i6aJ1^|@`u}w?=l`!y{JYkcahKF7zYy(4XAHaLAh7>kswf;WDJ8 zodnW*&mk}LA4ATyzs;HS z&jMIk)X1SUY8WQ8mk8qz!5gX{ac?|#KNXah-`{R{t;jx;+arrw4mTM?C=b`)g9B|K zKbe$=Z!xqbc>xxr!#G3cIJ_43-sk>0XiMsaXE3e+56S@N-W&nebhy1GS=0t{!`!CB zeXl$`20SDCO)=z#yl@A)%foXM<_FJ&aY(!S?qN9ajLc&>wDpF%>BD`=97%ujZX|^{ zkUJb;(Bvllh3Ak$Tkm1o9O@S+z@h#=rtsbrEayd0}DguL&kx00m+ja=Bpt$)C)Jj(+GE#@N5{qN_YooPx`~Xe7HP3 z{%{$_+eqqQIN>I3Ngv^P)=&zdhx-v8M)G7X!|w&{r;s|*7v>g7Gy(!cXqP3lRov@8 zR1fWh=MwT9Zqok0{>Y@@?`{gwSN{7?L`gvE7m2*?lX6LUm1893w2Pdz9?n{^!(W2e zdWpaFl9b@u0BLprBcj#q)KgjW@7iqlGG5Yvz*k2E1b+8G7f(?i1&vA9XxDLyUk5nmBs6~80?xA;He-^DJ8RN^C1NybWMO6ExxOV&s>OP-SKlxQUu zNxCEtRJdwMgQQb(MDmQ}tmIiqujCEMHOY0!HkBMipnS7>{u``WKCv$?i#JtM9$^4u7g87d5nYqQ>kup*r>4Q>U zI$1hRI!8KRx>mYFs*@&5bEW0dI%&J~sPvTdy!1usRp|%PFQwl}f0q6xb;-PBD%k|t zY}tI-V%aj;YS{+aQ?dwIjLaxYk`>BoWsR~9*)iEk*+tn)va7OpWS_{smHjSrdP+V0 zJk_4#J?D9@_1xwe?HTK7@=Wl|@+|Uf_B`o%#`BWri=J_T=4`v|*&UBhl-L)Zv5p0%+J>@(~s_AL7X`wDx7eUJT&{SSMK z9pETV%t<)~r{X4Z^SBk<7A}m7;^H_fm&|2x`CJ88%QbUt++pq*cal5LUErSMUf^El zUgJLCKIVSme)FQdBwi!E`Us0Q z%p9T98WOazMw1pS4`!>y8fGSUh&Ik-O^&x{%~AT;IIAusHq0EYwdzPtZ?PI<%-T3( zf;Poyj0@2lgv1zcHAY2Q^wEZ}*a%}ZXpR=04ir-WpbZI&wOaLYTC*`MGSZl6h=r8Y z4d>%cq(*NDHzt{4!;(WH^yY|Ityyc*hFL*fHES(8GA!v5YmA7AiVce8e_;!6kC&7Z?Hyy8O0n%G}drq zY^2^A7ORi2YLl!XIxW$Sg>0fe(yD_8(T0#%Z4_w&Inczd&{N0@YP37MFWzF+MkX06M(8q>71~9GMQF*2ge2%AwMG*R7f)W-5CO{_W(pxQ1Gtd{5P-01VNw=dm{|+^ z6%j+0-eT37Lc+r$ViLp5kx^l=IKzeEl&qvF4E7NA%LH2ey@o@10m4vTyAQN~fSq7A zx?gWNFHF`H8*d3AI~%7r4CUPWFH{<1gk*m_30u(tfF`iWB#nqQTC}hv2E8F#m?SuDFTQn3UEkkc8@TWC!-F{GC^ww z>q*$~q;*EKK82V{VgW}(B4CfL)4q56 z4)D)xH0hF~^)O1fFcUYy3iJruY7hufKutIFVd8R^gr`Ecp*I_TDL24)U$r5ORbRg-pCjNXR?8@hRjlg!)^B z(D!dOu%iM74)q`)qGOHW+C($Zqs|&;iLn3^gGC89>$Oo4U_&EF=f-R>g=zQ41JxU% z^ai~(IaX`22o=$0BPn|0z*CK8 zK%DqkW2^;?Z85-a0Z6ni9$1JOKmq#-j|FR7G;j-Zd_)ZF6-)}K?p{V%Lg*B4TBUeba0p4h(`{lkhnUa;!S@mlEwb3uRAAna%X|R34lqnNUbFX_%$pF{0bXxjWdRmGt^CFZcG*MWq&*% zpD-JDPJjsSWiSA$4WFQ~!(L z(g@%$q;&`!M=`(;0H;FcJiPEeUTy)bGXu%#O;$^MxH}UvXTe-kd`b#g8@(3xP*30x znc%M+5eqCjy*4&-n6xnX2oC%!5s^Uj?t@SuO@S=#uW(bx z{WX6b2|^FDjXG;w?7RqzWiB8Wa4|QJBTGftngtFZz*C@qy(Q$Y1K?iO@DUL*ch+1% z9wK1j&>$1McLEb&Zk8+5#cF{jf&aTxfx3yPAYib-S%s<1oju2WfRYkWB~Tuak9)I+ z(-1(skh!xT*2bHo!{JN-dNJ<8yjM5m zG60rH7zk-~uZGNixK`kLe=CruA#>*j!96b-j;Z)?t?(j4`6Spia^GJE{4Ojx680Zt zNWe8%t069;H$XAk92OS^LR}2VREDV856=$Q!%mO|6<}C_6UCa{zd}W<5upDiblg`Y z4Cvl7f*bc0-6U;-JxByu&zNWdaxxqBk$}(fNs-__0UlzBNj3priZ@%}*dQl4?7A@u zxFO-}z(C>X2fTOs4u7+;J0*%HiJsMQxqoBiu59bC{I)* zIwpEv)GK;ZbY1kl=qJ%1q5%)ugY$R_l;6D`VIDej?~k_t(Uq#ab(*CcOB-jjSFxlRYtLG(g8nl{qO zbOHT5{ZCLqIVOM^&rD@zGV_^TOav3dn3%)Nr_5K(_smbsZ;XR+Nxh{3(y`L%(je&q z=^E)esaBdKO_%0LE2WLn1JX|EJJNqkKa+kfy&=6R{Z;m$EI>A1Hd!`RHd8iFwn+Af zOe@pN;$&u7o$Qe8lVqKiD_fkJ-=Jui1W386V`Pb1S)E zZZ{Xs={O@7&!utMTpf3Udy%`wead~q-Q@bYKfGjKDz6z{L0&7o9`}0EYlm03m(I)J zmEe`?mG4#O)#laVb=0fN>w?#dUN3vS=Jl4>2VS3feeLyw*Uw(Rc{#l9deh#V_egJz z_ayH*-iy4Kd2jIE?ESR2*4ylzxhxHlZ~0u+4bSNe2Avwqk&^$DHRv=KS#CD3;S~8SQm|;x zN%uXOg<%H!6sOWpT07MECb~&~iaal%Kr~kA@W=0ly z{t+$Uxdi~XHN7!e%}J9R(_7UXGlAu{@LgPTdU`T9mC4D=%h61g=2Yj|)i)V?b+ui? zE#uW(1@DS-MfI`{o?I@T&abi;)~M_?7x@=n*uipt?Z;r>c-GlBp66Pcnp(J_b~W~k zJU4;W8IE;z9Xr-_5FpZ3`8gH2s@$By{Co|!66RIRN3*C1^>ST?V>+@U!LTF2up`?- zL$|?lw4^nqr~{nKnUu7&6b%lRrZlCsr~{Z@h76@~^htykcl!R`V4$yrCB3Hbq$wn746_@NOa-3Klzp2l^gn2VQjbAuo0?#JQLL z$Mz}bSE*b<%<3&$R%={A(pBfD{9}jO88R43TRRf@j!umu(~;H5a&uR%M853YmDj$} zIQyjET)Xy-no~>!4446Ue9XYDW$(ym^9NXsBiI!j&bBmH*VjYd5uCtsQXS7>`8HO> zDbN}`0?ouLy46Rz8=vn%p8Uqm@ezB}D0m6pght^=)w6thX?kgz2G3qG5zoOZl-P#$ z;62Eu9_V9|U>i5{jy^LBsJUYYou6NrldH_F$f?R#6Z}L^@PMpQjwrgSs={8Q zoOChE&E(fDVqJZ+_^S(9K%?|z4Qv@&$Gd6owP0l%>_y%&IxVx)7#jOLcGPC4#d!g42=Yrv!#JYwQRKph}ax;`_tIz`20);H(1 zsJH++i<8d1wvyoE7px2R-tQK>V~5{WU|KHT4=~~?>;J-zTfD!37u?D8Q>s%Z8#$yy z%h5wD_x>xdywB+ughWP$WMyPzRwT*3=TpiXGn-0FZKbMbDvnhisqR1g!-dcPCCh&K zU-?&5z+T@$$>=nPF5$IkC4LdF#0#)`=@RwFOYj1u#w%4&w-#zI;XGu*dusADPKoOm z8YZ0Itm0}4+W;2`1!=edNfwuq23(9Y^AiBwidZ$*g5O$1LZ$6+E(!Uc|#A>nDKry|{>zcC#+K%kF13+aeB` z9VD9p6UpVd$^V7B9CH{zE9`mIIchS3J(9JvNG|5m;2dy7E#^4~49g)Y8pA2@Lg!dK zg2BOf!)Nnef3=~Zrna)izq+0-OJ%Z4GBT8|Rd_LG9C|4SxZ~=3jfW$p9$pYw$y_dg z$>JhlV>uJMiW^X%#R@E9a470Q>roqx9zaWQErSDbk~yp(uQ0DT&%cNvuP5iE^LQ+u z26PNWna=x2;dpDwYtF2PX<;eXb5R_ zZZpZ*jjdH0&h{xRQ82^3_v)+fai0dznTkb#fpNA>TZj!$wMBp(y(a5G+OcF=O-IX7 zI1yn7^P5|gEmh6+^=fi-zRxzcYPfTi=c-TFqDL>HS)ZW?kxW)_xu>W{<;ZnRKUuRK|0& z{yIfL1XJ`OLv>qeQ+d6Ac^h59pu}O!d{)1 zv*gVuu9H;FWrMuddxQ0v#UA3Pz#$I+SM%g3Mhc$GgAw6?7&+-zJQ9zbG>QEFIth(L zBY*uBja2)zlewX3ESktVZS|5(mkM&oHz$Xv$b>E&ZkH^c3ZkKeyP{@`J>81Zl|K725KKL~og7cTUw&+r2C zUk9>oB)d(Z#5JNP*mUmDq4TywX6_8%+DKj@yYsN}P;F;x zs~Sy06X}*#uDQ7i4t1y4@e^&gBNN(#@|4_eym;lN^{dj7Q_?EUGMmj-qU3N8NR(vr zL5@U0AW!DyaDfW~n7L>qoU7ycb%~=uC}_($bO;~RAg|+gl_}Tm%SPM9pFM`C+p(U`f$Ogj39`p#D49F9Oe2B)Y(1=eW zw)bneg>cL|gV(T-@p*5{tE=Jcu_#{Qxp*GXIvt3kkYHpQ3rMZzl>31_u>s6-4t1k$ z+%4rq9}T342VUdi$!t^dQ!_JRmu7%?geCz#$k7y78#|!3og3_v;<;Rny}YW5!%{qk zYr=}g#4>emYj$g9vy8LVs?h8`L_|TiBLNz~6T}mIn`7Q#x%%eXmYM^ywlbt>Y*KQW ztPgGNM5|#@Lho##(bo(L9oRr~qe#cANDc%f=kjIw`MHHTDlBJG(mA{ekB4g&=UR+@ z#y>k2b08anAWukZCeRZa(ch0ofCOX(Es0wN+K`%qt+#QuZ7_-y0m}#2?n`dsD*wD% zU9TxGD=jNm!ZzETgs?z(%&2dH6S29assTs?*$2o*DW}7G$(=zkCn=n0K=g91j%PTP zO^O&KdH%vD8V)3XPz7L>;2B8w07~qv;%G|;IoyGV`0yOvTG|Z!pBsQ#a448*<@V{7 zdf2gEhBIedl9SbV5}wF0Z(rH8R)gfF3J%|GPxzE<#INuQA;=Fuj>54gr^1)E;a_nA zo)4mW8(@oc8NVA2@UCNk;D%})%w{#z2H@ok=K_g?v+@cKVge`%egi3pAfR$7s)V8% zDeAC@I!=iS?|Kv_iSmi9WFEB;;){P5Rf%dKM4(>OC~6j+5}g+P=`qz~g~xw9Zi~l? z6U67mcO<+dT5?YEC%uhsrC(z|gAE zO*vJ0Soy8esY(oZgqQLER6n4etX{4*s1K;GsNYi~jhAMuW{;*_b1QI4;QGKH$2>CT zA7i<(=f?Sr+dQskyn1}e_?r{PPpF*GHsRt#zlr~zR50n=$@LGNnX+igA5%|F+cqs@ z+S}6~n7(}aZ!^p@%4hsObLz||W*(ijYF6oN$QX$5KDr7zAHmywn^DlpJ_O|_m=Lh-A{Et-MyoGSNERokiok) zBnhB3NFqWKByj{Ii5OXtL=iv-I)VcRzH|jku>?yL&Y*4VU{JsS#rOmaeBcup%p(vg z?BW3W4M&OsA3!q@+*i8Vuj{V(uR|WXD@)op>iqEmJe@|bq0uaUO$x21Z|quaWJ_xUXAmZ_~hhx4bGFsw0wse^@d)0B zL-DjAP%gua%Yc&7*ptG~HMb>n%yYV^Ir+quNu8Y~X zOsAO}fxX6IZ{=QTe4}1~-O+ORpvERWcIMrGol^hUixhq6Nu^Kwy$j!Uz@hXT4-9Ss z-^eat$rCh}7lHN*%g%HL&}$Su8|+c)fPpL~YD3OWLx-U)QRDO)^r8pth-2Z11unc6 zgng%-ae6tu=(e_wW5-~S1W_f(E39}MY+<0HH}t}`?3|LK9Q9xyw$l+A#;7pmon0@m z&K*)1ESq+ndV%!`g!5xSUcduLyEub)22bZfY4K@?Qx%R1r~Nu#$Db%*0|u7If<;f- zZs~|Wl!(S*4>TT2kOs?S>p%Q{+3%`Sh&B5C`;XrEP=ho`23o%ajYA%X+By!lcghCs z(t*>G`3tf5iS25v9E+7>u>TlY=(eddSF1{x5@z+(?=Ec9VE;d`68_zm&3^yMUl5~Q z0Git}{%n4T8P1e5L>?Gep2ptkLk#cJzMcm|(|{by6<_nIywA5V(E)G8Gcom+3bm`G z563%p(Fbx;4q8>~c*j#Xi_WWWENE06tM5GgA^R;KAldIYrnu%>=<-IpTt0YLpJO5Z z7ka_5=ykNkF$!&QjdCo4<9+{Y{}-4YM?Pfn-Sr?2iLE?(P=OM*pd0w2DX66fl@N?-1iD^%I(}!F>Y{#DE3uA#DGd2hEe5<#MzbG*8eJ9rAVS*a7>X z{S`8p!61R*K0CV=3?EN|rl+Y>-AblM$u#nWsCFL|0B zfQG|)pZ4~I6JVA_-Cz?4mQ3W`hJitlTLhF*gLObK6@qDS+lA0x(4E2J0agpr&cu^; zCO{MD_+OBcSu~yntMX9y*I=$xBgAa|S3PuJ@wbLP?TrDFLn7oI!1w?W6b|fFfXJWR zs>T5*;3zvdesBW5jGjNr;s6}*4v+5OI|y>`@(7+gbxs`u84}+uPY@vw00iu76xufo z;xcky3)%Z&;>+Yhm+!$8%J?!scS9CB;mhtZ2z){+m9XdqJo!a-xeFw$i9EJ~O~`HB z##U^V3ifpbIY!5;!OjkR*D9R>68VYgd@_*MUtkE$$-fkUxcc07c}E{~7;XvDpX)Cb|1|XFuvZq>JsB#)PveQe{;jxBiN^8{5K0jUrRqVzDg~18#Ciz@>FQUv zymy! z&*Od810Fl&u{>a&NYRqnoKmjF>yBohOh1`&!vECeGZ#-?l2ulhSKE~}#We+0>ac&U zetlbytST=DEOI$HMPT2?V*?FMarLpa{zkN(ZYfS}NLFDp%px@Hdbg?*+HWKXULd8 zkEK16c|6zUdZ=x9l%!V#N--vs)1Y?7`7@ zUn0ko6}wEv0^s#bf$8Y;nt{g#G6c;O9Rxkp~37xp$cQT7Cj!TNVhT`^& zI&4Hw_&KKS_Q{rzgsVT3nbUxjS!=s=ByFFeTQM)>Kqhz5aopk1G=ntHm(bZMG8dQ$BhNn1}_Fh1}7Nti)0c zsT@ogRyZ#PtP12$h;{@IwrJG15JZTZim@zu2-s#H3a(^DF9b*f!~-`SXB4TWX_;v% zT*RcM)i;-FDx{sz1Pp>3(E_#;_tAw?r_B|uIG=Ss?X=o8Z{QexDBE<7`o%{7?Ua9oUL)qyK{_Ai_VIOP#S7N&Z?ckpe>SiZNU9u zm_q=i4bJZ5(sVGj!PB!f7mo=XL{82L5inMgk&7V{T*SK~8Nwgw=%`(Z+g00lwVjUA zU=<3WUD{k?Dq6tekKu^y$hJ1`S7AGt=)v}92iHh2woB0rmiQX{&w_)RM|6e?WpRxG1qwgX1Z!msyPF7Ub7d7P6Vlc}3fyKQX z{8za}`FR?A4PT@4^9plwl!99goGkcu9*=ILU}-~rO?{;X|K@0ah;2_8fQ@>SAE*Hu zm0Ehb1*Q3A1^#G9oZ@s=Z~7@U&T;h6C(|Pi z>r_B2x`_Sz(lt28)kCN2v$jPmT?xPQJ9rqtDh3Y{nDII?+Y{^5u5Q$qRByH=X89*( zW+qsbz#re{>&mNY!JH4q<+i%|_71QcjvmY20Be`s_Y9ba=Ca)^9*q@#$RFGQTd(6C zD%WBR767mVjOD@V9ovsqp^2K>2HSzmI?N+AtVd2c@Vk*_I(IXT8ZbX?y>VB zUjx`hNA3vvLF4-_R%7+suyd>U8$5c5_dOFpf9J3&TGE@)C^juSC%r(E5|OF3M9T2A z8F=ALyha5M-v?g!X1a!$w-VTSu>AxDq`vRwfu|HHXh4~0-SQeQgF!}1ZYz~VPn9c zflBaRv=`n3Qn*Usc#Ek45eF0^LSR7lb6Mh?HnDpSg`cyk1F(JR%Ob?7Vgyf{qpy_(zgvuS>Vj=cLo{pa z>7>`QufDBBFQFGv3;F@B7jX-I>9Oo}NgLE_GwF{*7W7V4osfp`C!~n`D{ zw)N2Ge`)&ziIhHfGEX#uH_&MpKf(LB?vesIuAl_mzgzL^#-FF3QCH;Vl;)~*24l45 z5hQEJ5XpdL?T;vL1Qt`RP}9%>a6BA^|X!|NjdB_-jxI_CZ_l=Idxa zYiv&H$kZH3Ka|;-Ec<2Ut6=@}QDUDhSUP#7+LCO}G^NX|nW;%eh5%56KxP0ZU4iv*KA7w1xTwa7;q_g#*D8$PI$hF$~8E;@fbZi2er?M%mste&UVe zXw>l^U;pv=3AlcEd7Zho235`~JX|gRb zKMD8VG5SSkg(gI)?#yI@*VMn7sL4H8YOkr6)!UoP8&pmwgM1I4LNhLF(2)Uk4S`SY@Fxs`Oc(;0h69>rvKnWwBS-<;xgEr(x6DibxmxA2GpmIW%yoQloTB&TirQB-&)3iy;JKCM^{C2fZQ!-8vmGcos@_>` zs?06jUahZ9ZjxoybQv>rMOIl>wlW*yIdawc z1=gI%9Q>fsugF}o-=uuC4DGI?OOHNR`nu}nH;VJ$(-gdSwdhq6NdZ#d`u?6~~Z{9B`t z1-wD7iVv{1TrJ$)^S%f-D(W5jPFReasvb;xyJU+{ge@XLF!sW1Y>t#pxHf&n1 zT#>nH|1Pz8XL!_BlgzYrRr(xN=QBka^;w~<(os*A)DqVV3{f`x~wu*<2rlCTY(;`{I>jL zIg(cYQuReK+EM8DP0?Fb7i+$1ey6Rcv#0a&>5I>wJl%P&@mbk{muvs|59Qaf*EhbW z_U+#I{v1%Pj(mLjABWnTWxgjboH*Xqepc3gw(i1Z<%PWN^t0;pv+-Sq_cH?QCUG% zdPQ{U<|=F`!^+a9%Ut<>^NXIy4^bDT=A~pM$7FvlUt%w-s(;S!0?Is#=3GHno8CWo>lpI)FKe$jT79zST+OkX zwj*_?YR}i6x1XsyQCHPo(E_mQ%IeFS(o1y3!G*H?$*YP&RM{3=S)>NP*O)ZkUffX9 zT;l&u;qy61(`3n|nI*aE+#T^)mAc-5XO|S1md4@P{+a8x;&v0(YMUovWmkUrJ&Pu zXoQi+mlzyVO8Y8*2502splvA@57<9pE;b(RGHHC@z@yN7Q&))11UB+fcs{K&H5xCf zKDlFG%!H&Hbw@N1lr{f|?xO7oSi+$#0O~rDel$eo146*S?V*`hq6(0H%NP%`pACJIXr6*_&%wUIKAOx$>g;p&(WnhH6fYKMq71sza*elGHFyzT zNPIVF5n6Pb9n8$&3wSgMoXv3B$C6Mh1fewGk~#e>zp;A#;b65xG}uIkv|TbiuX_H{ zk&Epb2jy&{55H9X#uX)4CZOX@#Zq2#rw<$&plbvIOi;aXCP=0bJUn3c-RxUQ+%1X* z{>fL~SNpafs_Cq6Q#Z8rzSI7;tgaj)tW-6%1zF{q_Q!hHHYCdG6KgDHrSE2tnfv2@ z*#3!n`zLrG>Rg06WEV2S+hbHQ5ecCgnnkz+d`6wy7t4G@cPx&bJ`uY72A&*2kiR() z6bXoV6U+i~@qib)t=M{V>dOo`ML-S4(`fXOqhDdqDM`!8!N1|({Bm;AN^(==Jist4j@u&|VHkfH@Du$@Qy2AQ$ zyS=B!4Apu-Qm z??=AR!Q1>cw5nx=g{6hW@|2gSS+|amKUv#qsXH{+_oKfB=iXcIlJfGBa)=elxEVFOi~iUHd&I=pcASXucdT%& zI1%%L?ZgRx=S$9)Xz&P5Vg--jbHH8UD3D7bnD#I%oeT0z8Q3~q@{90U0|W>Iq7TOh z1NXBNgAP&M96-(t7<7ax5CV`lsF`;0Kr{)mF%V-31dg>2)dn!v5Y0Px-e3)^bLR_u zAk-tD0EPi=Wb4oq5)tMOdh~ZfmOf-|vv(;;YY^!I0+^8?SJRo`dC@ukP#kZu9gS@X z7R zCS-&8Ac`H_`5nyExf3wSe-KjId?+zTryShb!;;qltDAkOl@Z$Z084;cCoF^bIV@Ee zi3{;N-Umb2864mq;zq|m6=t(Nu}cM>#x8r?A+v@+MLw**Gn*WdKniw(tq8euTdsi8Zq0W~rrMOat z%m0Qa9T0xxB&|C-8&94BV}cy@fj6lSv`8TpH^P5~fbH1MJPwr1O5YI>fq5L>0N%zO zpw)L380LDgt&xsGhe10dgc}3xt5^u(a<_ofE8Q_ik&>4J5mvKj)0vr&g(IvQf*&EM z=Wz@dRD$rSN=YG=v%iJN&b$_g?5u8v$WA1*LC~f?kA!H=1=V$Z2@4m*i z!)jf11|vI|n8CTKI0gr=6lqxSh(fRxsD;zUZFwYAz1w8iX;p%+pFb`A>8H=%KcT*I z^vK~Cl@~X6uZ!LX%cM?9PfXsuNtT-rdYCFNudJd#gZ+NZs4Z-@H~OP-Um>6O(8DSS zoDRl3UI$DI2g5tT@K!iGt*{MN6a;gygZes?bp@Y!A_yRcap%RV1Aj6_&7Kx;2d?wJhEtaB~olpbt#z|334}xAjCm}zo^*y)xKLutVI8W?{JDyFB1Q@ zZ_8I|ht9Q2;aCbEKK)ESZ-CDnes(Q&ErZV-ejfVF;b+G(wNC)OE>Uz9__G-Nz3=RO zZ6z2L7<36;qB{jz2UcO}R4@MkgsPa&d5c9es2Nn#RuU84VO2XdgMo>XE1Z^x!2y&xJLkH-3zbN3m%kH8KljihAJNb-ug>0nsnuBd*6X?d6;)zd+r*T zW2CS(mmnq)+H`6@{E%?I6J&tp0rb`DATh%L%b^w|O)E&6u#ND-5T68qh?oB|I~X|p z2@cFJ@H7ifZHSfthPe--wSjaqP6Yd#K)hyrfmUFjYbnTCJU^_5+x3N53hR# z%hh$(x|pT}S$1`GUZbk5zWG3NVQWdVrl`BPyIbklk4}H?SP7qr0PoF%gUtaaGMsqM zLWgx1?>y+dy%z!%qyh8|Q3L#d1ncPA3r`1b?*eB7@SU5^Ai{UTK*kTiV-(5hX({SM zd~#Y-s|GzOZEb1-=Sncs(wLU4DMm9C=_P4d;9uOpB&F3gYEqmc8a&F?73#_=d%0bO zOpM)LR8XaQxY8$jL6_Ykc&_$lHY{ri9Qr?lgOz-=rM)PkfMXZbcU8L&C61U zPD*?Y2U(X+x>f4h?fglZc;v8 z4XQz@C<#qQf2!cj1MkmH#g|cl&Gf^j-P?oJ;GFSuJ$4<3t(D<3({U9}#P2J0<+>`p zx+3xLwwx_^=b~}Sgz9{Iih9qH1F>&>{Td2=L3RG-`qbw&u{VB6y{SUe(A4wqAe9D; z`f9Wr?Y)Yw${Ma#zj>8d_#v(fJp@s(pg{&fWG{s1xT8FPC^iG04cu0s8#oI-dO3!C z)ukmxrS$QQT{BkW8dtF1<*URuP!?W^j$vPQNohq19dkwZ{d=g!5q!$w3*la{n*$Ow zUgQWyI(rdKs&+03P}IdMxon^wJ+EegJG^7B0Xxyc%CLKZ^bQ;6Uhr6Dl5U z*PMIqT+i`;$Qlk-w;v`8L*z602~b(lJVNvDvqSXW2=x9Z55$h2lomT!MMg4@`|!bbNtJ)t8(lGj!JyO57)!Bt(Pt>F0vKDH>o6MXX+Gi=;uJYQV7SX zDF7jBiywIBDywp93TsRJOKtE~7}!oUH*Z3GK79S*zYT3e^>CeVRgw<&V*iqIh%Zr9 zSC>^(g0^$Bwx+V7sNNq3IoG3kXx`16S5eTqtNx(10=0Et1*sM6Fn;`rt0#cl1;ImD zSRpS5K1Zw^3dHeOM zu@muwpA$d5brnd044QhC_)A~aod2Qw`&c>N|F)9h5%!0F8W~ zOX7qE><;<;HLE}y1wH9Hs3Sy80@-H}q@3Y{UXUS<^Hw5*49O3md?gc|=`UFU{A{4D zfsjB9Qhx~vM5zLGEd^u)kVD*p1(97&Lo5)Q4r>Qeb258EQC(D1Sf$265MffCpAA7} zu0Bx7gPCP)Q$bU99Yk<~t)Ve9xh6@Kl$@ImT2Y@%PG@Hoq@^K<+=iYnHXFSjIS=0spgd563i}N>f zk6XpVsBFQsxjg;O?JtUpi3k7a-Q)VbjFxT zvu)6pLrfF{lxH+gg0LQH5P-V>h`o9|_GVmVuA$1Ut2S;}6C%w{$x2C4(R#2LTireA zGXTz?AH*3;N=>Ee2jA~L^BMn|dECX&Z;-VqG#0AMi!9bMen9!STMt!W*k*AJ@r}uQ zOwxJ#0$W;D`|_L0>bXB)X}$J3c{4?dR8nb)ib(I>Bhm|}!`AHMjyMjLHP^%~-Mo6` zw)brZ^7oZWu@o)zM-Yj0asEV>kgepk&VHgHWG&VNHI`!fX8XTrvGZR*G;ak; z_W2{SfrA;dl|CgNoxWurPdk&P60(Nu^~V4|r@17&e~&0W^3bDNU~(%E9)-op%uY-c z!!*o*9Hxl@^o{X&85^7#&^;#N47#r>34Hv6m?MO%%Dp&A&K~$gK==z0Z!KOreIzYJ zA#wr=C8jcPn25upDggj}Cvm6@vF=Xfc`&lY418P3?p#c^TJ*y6+{M}Iawy-Ig>1DK zY~u>H*|&zM-k0?pe*4j*+qWO>+>w@4$0gOJ?bxYe?;qVB-jj3QZPzMy(gsqpp^5YA zFX&!-O}Fjd=*mbQYb6XH(N}FJ(GedN384c>e;Q10bUcFbZU6}(KwzBws*Q6FYaiCZ zZ#>h|a>fHt=4mJiy?OObZ6j8`8bz?L28{2 zw?jE)-rUJk=AOM;r}^|8;JYqI*Z+LN$?fbzkl5X$ltsyf3BcYCtWMdHv^{aV?~eVu z_U_y-&9MQ@s@g$iq|>$<&YF(d2q6oj0kB)y(C~t={B60uI#4%?j0yP(YC21tkd&N| z!6z;?Xbnq3Q^JzN5~<{SpB&GQAwU;D7aGMQZ2-R`&61Xr&NZyxwPDBF#4vqW>NfgX zxDR65@rf!rQ<9LESY+hLz;MUbg3zK+-;i~|8$#AgK|X~5LkN-i*M)PyeIgfQ&ov|Y zKxE(5B-QHcQhlqzLP;5J54mbj=OuLx1%qt?^bw&`B{My_)@>-2gp*gR(Pz9{PZ%WcbGeJfMYUJa}R{xq( z!4Wm+0@+>hv3$}5nLGtwdB2d)!dJ|$Z2BieX4oF0#rORpS2BDwoUT1t*y&<5l|L z6PbO#Ve63PCayBPXnBxIzSa7(#u8(Wjs~D}bToL~v?1%ZN$GZW z!(kqL9+nsmT)E>$aPm%m1+I3V)#N2Ly7HrVueeoKd$91>F;#VDO?nmAaHRC?IaN1U zZ&vTC^W|P??H8 zt(!nK+>8$!$*cVzZrvGPA673t_b$aqj8zAT<+D#>a3p8$?kzvX?;}qU@g5?BC5kU9 zNte%;U|{64t-UaPaW-@T5p?cToA-<*J~B<&ohWw)w!cW5@;|KTS&P zdM@^C&=Jm7WvQuF;Sk3XkA)rN%thJ7MXHv_mUYKCt3-bAB$=I!*|QU!uBKhZbP#=E z{Sx{zpByqec&nOX;AWqEGK|~B`?q~EWY@agEBCD0xAy$>Ep+Iw{iNP-%OAfs{d|!=I z%ex;^FJ#^vx*H}$k2uZ0HJ)?}>4_CsabMZA&Jc#Ys@R)F(Rw9Lnly(JKiTo73>MNq zq;8P#^nSs+0)*yGh>sxm?VNs(q>+3~)5-AR<@jg7zvM1>+fC`5PU709ONw3o%D0y+ z7|mswByTJ^_0cCMPF%l!bkVeIUby+#Unxi=_cmXCea8A#Yhts;gSNn2s#9Pz3USvXoF>* z1qz5+X8?tr|2n`1gQ*WEI3#r%uqSZ+d-PuzdxCevO7{WvelUFa4`d{OX2>D4?1)DchD@fD zkx%dkAp|kmQ5vKI{Ml#3kIgO2u;~m?lEMpM-UP%pX}gRT#qSnQ+qz-D6$q_np!we% z#v?kG2bBWvH=AG#w*FfNQ__W`u+YjV21KEFU3k~oQ%RRJQ(xlui|RfS2y{pT?e^Yl zoa-{#q3lO}fkjxdhI{XB1CWzLfSViu(}yU&meJ<>;tZL)HC{G=GR2dFGCGgM(hcOp zc<#XBrr@#!>B(h9OJ=BM1i{H1Fk=7*NWK%0{1(am0WAXt1hurZ6dgNxgexm*+I8T# zlzdnWQp*O$sKYg~>3mgubySt5{$3Fhd@G5fmb|miIhNGRb505zc}JO(V|1k3puUlv zVK8KvQ|##wWHRMgrSb{-)fbf+_Ed`@!;qN;Vuv*?H#5f~&5~GivT_Y}>8uM%b55o; z-2&{m$(U)(uo!Ha)=Zn(Y?0OnDswC*yTN9#rXh)#k(r%lO}85C#+)1}!T?>BW?Q-) z$N&gO7?C!&r8$gJd2c<)gch?+dfA|~r&?1?TuPcDJ&%jV_J>m7EhjX#&CG}$0P zV@ffmr)Q^Sg970&18-w9*`%(;t~pG_3l3q!?yMtxnd!T?G&{m;R=oLg7VQ$ITGp7= z0HX<~kKqLViyF`ZX25vy#L&qLUWauretq((&qI0l`2SD>mMinB4LhRCn7V~eVN$Fu zP8}EPK`3b5+K*vxxV7R}@zhr)XmR%Is!M9}cy4h%WV1ykvRAQnh@pe{fv& z4*p=(dxuqWYvqlw>o-&+{ZrCN-X*Vc=MP?M_+-0u_wDcZ{HT^2{IRNumXT-n?|1B1 z=UB5$IlSCH!4a1o75#4VyDL-+@C;qngg&E|n?r_%!H$Fxa>!;Y#Q zJ9
      ","
      "],tr:[2,"","
      "],col:[2,"","
      "],td:[3,"","
      "],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
      ","
      "]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); -u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("'),$templateCache.put("/views/modals/choose-date-modal.html",''),$templateCache.put("/views/modals/confirm-trash-modal.html",''),$templateCache.put("/views/modals/login-modal.html",''),$templateCache.put("/views/modals/pubtime-validation-modal.html",''),$templateCache.put("/views/modals/send-to-editor-modal.html",''),$templateCache.put("/views/nav.html",''),$templateCache.put("/views/promotion-tool-article-container.html",'
      No image selected.

      ·

      '),$templateCache.put("/views/promotion.html",'

      Currently promoted

      '),$templateCache.put("/views/pzones.html",'

      Promotion Zone Editor

      '),$templateCache.put("/views/pzones/carousel.html","
      Looks like this P'Zone is outdated
      "),$templateCache.put("/views/pzones/feature_type.html","
      Coming soon!
      "),$templateCache.put("/views/pzones/list.html",'
      Content IDActions
      '),$templateCache.put("/views/pzones/oneup.html","
      Looks like this P'Zone is outdated
      "),$templateCache.put("/views/pzones/reviews.html",'

      The "reviews" promoted zone has no available options.

      '),$templateCache.put("/views/pzones/twoup.html","
      Looks like this P'Zone is outdated
      "),$templateCache.put("/views/rating.html",'
      '),$templateCache.put("/views/slideshow-pane.html",'
      ",support.noCloneChecked=!!div.cloneNode(!0).lastChild.defaultValue}();var strundefined="undefined";support.focusinBubbles="onfocusin"in window;var rkeyEvent=/^key/,rmouseEvent=/^(?:mouse|contextmenu)|click/,rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,rtypenamespace=/^([^.]*)(?:\.(.+)|)$/;jQuery.event={global:{},add:function(elem,types,handler,data,selector){var handleObjIn,eventHandle,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=data_priv.get(elem);if(elemData)for(handler.handler&&(handleObjIn=handler,handler=handleObjIn.handler,selector=handleObjIn.selector),handler.guid||(handler.guid=jQuery.guid++),(events=elemData.events)||(events=elemData.events={}),(eventHandle=elemData.handle)||(eventHandle=elemData.handle=function(e){return typeof jQuery!==strundefined&&jQuery.event.triggered!==e.type?jQuery.event.dispatch.apply(elem,arguments):void 0}),types=(types||"").match(rnotwhite)||[""],t=types.length;t--;)tmp=rtypenamespace.exec(types[t])||[],type=origType=tmp[1],namespaces=(tmp[2]||"").split(".").sort(),type&&(special=jQuery.event.special[type]||{},type=(selector?special.delegateType:special.bindType)||type,special=jQuery.event.special[type]||{},handleObj=jQuery.extend({type:type,origType:origType,data:data,handler:handler,guid:handler.guid,selector:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),namespace:namespaces.join(".")},handleObjIn),(handlers=events[type])||(handlers=events[type]=[],handlers.delegateCount=0,special.setup&&special.setup.call(elem,data,namespaces,eventHandle)!==!1||elem.addEventListener&&elem.addEventListener(type,eventHandle,!1)),special.add&&(special.add.call(elem,handleObj),handleObj.handler.guid||(handleObj.handler.guid=handler.guid)),selector?handlers.splice(handlers.delegateCount++,0,handleObj):handlers.push(handleObj),jQuery.event.global[type]=!0)},remove:function(elem,types,handler,selector,mappedTypes){var j,origCount,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=data_priv.hasData(elem)&&data_priv.get(elem);if(elemData&&(events=elemData.events)){for(types=(types||"").match(rnotwhite)||[""],t=types.length;t--;)if(tmp=rtypenamespace.exec(types[t])||[],type=origType=tmp[1],namespaces=(tmp[2]||"").split(".").sort(),type){for(special=jQuery.event.special[type]||{},type=(selector?special.delegateType:special.bindType)||type,handlers=events[type]||[],tmp=tmp[2]&&new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"),origCount=j=handlers.length;j--;)handleObj=handlers[j],!mappedTypes&&origType!==handleObj.origType||handler&&handler.guid!==handleObj.guid||tmp&&!tmp.test(handleObj.namespace)||selector&&selector!==handleObj.selector&&("**"!==selector||!handleObj.selector)||(handlers.splice(j,1),handleObj.selector&&handlers.delegateCount--,special.remove&&special.remove.call(elem,handleObj));origCount&&!handlers.length&&(special.teardown&&special.teardown.call(elem,namespaces,elemData.handle)!==!1||jQuery.removeEvent(elem,type,elemData.handle),delete events[type])}else for(type in events)jQuery.event.remove(elem,type+types[t],handler,selector,!0);jQuery.isEmptyObject(events)&&(delete elemData.handle,data_priv.remove(elem,"events"))}},trigger:function(event,data,elem,onlyHandlers){var i,cur,tmp,bubbleType,ontype,handle,special,eventPath=[elem||document],type=hasOwn.call(event,"type")?event.type:event,namespaces=hasOwn.call(event,"namespace")?event.namespace.split("."):[];if(cur=tmp=elem=elem||document,3!==elem.nodeType&&8!==elem.nodeType&&!rfocusMorph.test(type+jQuery.event.triggered)&&(type.indexOf(".")>=0&&(namespaces=type.split("."),type=namespaces.shift(),namespaces.sort()),ontype=type.indexOf(":")<0&&"on"+type,event=event[jQuery.expando]?event:new jQuery.Event(type,"object"==typeof event&&event),event.isTrigger=onlyHandlers?2:3,event.namespace=namespaces.join("."),event.namespace_re=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,event.result=void 0,event.target||(event.target=elem),data=null==data?[event]:jQuery.makeArray(data,[event]),special=jQuery.event.special[type]||{},onlyHandlers||!special.trigger||special.trigger.apply(elem,data)!==!1)){if(!onlyHandlers&&!special.noBubble&&!jQuery.isWindow(elem)){for(bubbleType=special.delegateType||type,rfocusMorph.test(bubbleType+type)||(cur=cur.parentNode);cur;cur=cur.parentNode)eventPath.push(cur),tmp=cur;tmp===(elem.ownerDocument||document)&&eventPath.push(tmp.defaultView||tmp.parentWindow||window)}for(i=0;(cur=eventPath[i++])&&!event.isPropagationStopped();)event.type=i>1?bubbleType:special.bindType||type,handle=(data_priv.get(cur,"events")||{})[event.type]&&data_priv.get(cur,"handle"),handle&&handle.apply(cur,data),handle=ontype&&cur[ontype],handle&&handle.apply&&jQuery.acceptData(cur)&&(event.result=handle.apply(cur,data),event.result===!1&&event.preventDefault());return event.type=type,onlyHandlers||event.isDefaultPrevented()||special._default&&special._default.apply(eventPath.pop(),data)!==!1||!jQuery.acceptData(elem)||ontype&&jQuery.isFunction(elem[type])&&!jQuery.isWindow(elem)&&(tmp=elem[ontype],tmp&&(elem[ontype]=null),jQuery.event.triggered=type,elem[type](),jQuery.event.triggered=void 0,tmp&&(elem[ontype]=tmp)),event.result}},dispatch:function(event){event=jQuery.event.fix(event);var i,j,ret,matched,handleObj,handlerQueue=[],args=slice.call(arguments),handlers=(data_priv.get(this,"events")||{})[event.type]||[],special=jQuery.event.special[event.type]||{};if(args[0]=event,event.delegateTarget=this,!special.preDispatch||special.preDispatch.call(this,event)!==!1){for(handlerQueue=jQuery.event.handlers.call(this,event,handlers),i=0;(matched=handlerQueue[i++])&&!event.isPropagationStopped();)for(event.currentTarget=matched.elem,j=0;(handleObj=matched.handlers[j++])&&!event.isImmediatePropagationStopped();)(!event.namespace_re||event.namespace_re.test(handleObj.namespace))&&(event.handleObj=handleObj,event.data=handleObj.data,ret=((jQuery.event.special[handleObj.origType]||{}).handle||handleObj.handler).apply(matched.elem,args),void 0!==ret&&(event.result=ret)===!1&&(event.preventDefault(),event.stopPropagation()));return special.postDispatch&&special.postDispatch.call(this,event),event.result}},handlers:function(event,handlers){var i,matches,sel,handleObj,handlerQueue=[],delegateCount=handlers.delegateCount,cur=event.target;if(delegateCount&&cur.nodeType&&(!event.button||"click"!==event.type))for(;cur!==this;cur=cur.parentNode||this)if(cur.disabled!==!0||"click"!==event.type){for(matches=[],i=0;delegateCount>i;i++)handleObj=handlers[i],sel=handleObj.selector+" ",void 0===matches[sel]&&(matches[sel]=handleObj.needsContext?jQuery(sel,this).index(cur)>=0:jQuery.find(sel,this,null,[cur]).length),matches[sel]&&matches.push(handleObj);matches.length&&handlerQueue.push({elem:cur,handlers:matches})}return delegateCount]*)\/>/gi,rtagName=/<([\w:]+)/,rhtml=/<|&#?\w+;/,rnoInnerhtml=/<(?:script|style|link)/i,rchecked=/checked\s*(?:[^=]|=\s*.checked.)/i,rscriptType=/^$|\/(?:java|ecma)script/i,rscriptTypeMasked=/^true\/(.*)/,rcleanScript=/^\s*\s*$/g,wrapMap={option:[1,""],thead:[1,"","
      "],col:[2,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],_default:[0,"",""]};wrapMap.optgroup=wrapMap.option,wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead,wrapMap.th=wrapMap.td,jQuery.extend({clone:function(elem,dataAndEvents,deepDataAndEvents){var i,l,srcElements,destElements,clone=elem.cloneNode(!0),inPage=jQuery.contains(elem.ownerDocument,elem);if(!(support.noCloneChecked||1!==elem.nodeType&&11!==elem.nodeType||jQuery.isXMLDoc(elem)))for(destElements=getAll(clone),srcElements=getAll(elem),i=0,l=srcElements.length;l>i;i++)fixInput(srcElements[i],destElements[i]);if(dataAndEvents)if(deepDataAndEvents)for(srcElements=srcElements||getAll(elem),destElements=destElements||getAll(clone),i=0,l=srcElements.length;l>i;i++)cloneCopyEvent(srcElements[i],destElements[i]);else cloneCopyEvent(elem,clone);return destElements=getAll(clone,"script"),destElements.length>0&&setGlobalEval(destElements,!inPage&&getAll(elem,"script")),clone},buildFragment:function(elems,context,scripts,selection){for(var elem,tmp,tag,wrap,contains,j,fragment=context.createDocumentFragment(),nodes=[],i=0,l=elems.length;l>i;i++)if(elem=elems[i],elem||0===elem)if("object"===jQuery.type(elem))jQuery.merge(nodes,elem.nodeType?[elem]:elem);else if(rhtml.test(elem)){for(tmp=tmp||fragment.appendChild(context.createElement("div")),tag=(rtagName.exec(elem)||["",""])[1].toLowerCase(),wrap=wrapMap[tag]||wrapMap._default,tmp.innerHTML=wrap[1]+elem.replace(rxhtmlTag,"<$1>")+wrap[2],j=wrap[0];j--;)tmp=tmp.lastChild;jQuery.merge(nodes,tmp.childNodes),tmp=fragment.firstChild,tmp.textContent=""}else nodes.push(context.createTextNode(elem));for(fragment.textContent="",i=0;elem=nodes[i++];)if((!selection||-1===jQuery.inArray(elem,selection))&&(contains=jQuery.contains(elem.ownerDocument,elem),tmp=getAll(fragment.appendChild(elem),"script"),contains&&setGlobalEval(tmp),scripts))for(j=0;elem=tmp[j++];)rscriptType.test(elem.type||"")&&scripts.push(elem);return fragment},cleanData:function(elems){for(var data,elem,events,type,key,j,special=jQuery.event.special,i=0;void 0!==(elem=elems[i]);i++){if(jQuery.acceptData(elem)&&(key=elem[data_priv.expando],key&&(data=data_priv.cache[key]))){if(events=Object.keys(data.events||{}),events.length)for(j=0;void 0!==(type=events[j]);j++)special[type]?jQuery.event.remove(elem,type):jQuery.removeEvent(elem,type,data.handle);data_priv.cache[key]&&delete data_priv.cache[key]}delete data_user.cache[elem[data_user.expando]]}}}),jQuery.fn.extend({text:function(value){return access(this,function(value){return void 0===value?jQuery.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=value)})},null,value,arguments.length)},append:function(){return this.domManip(arguments,function(elem){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var target=manipulationTarget(this,elem);target.appendChild(elem)}})},prepend:function(){return this.domManip(arguments,function(elem){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var target=manipulationTarget(this,elem);target.insertBefore(elem,target.firstChild)}})},before:function(){return this.domManip(arguments,function(elem){this.parentNode&&this.parentNode.insertBefore(elem,this)})},after:function(){return this.domManip(arguments,function(elem){this.parentNode&&this.parentNode.insertBefore(elem,this.nextSibling)})},remove:function(selector,keepData){for(var elem,elems=selector?jQuery.filter(selector,this):this,i=0;null!=(elem=elems[i]);i++)keepData||1!==elem.nodeType||jQuery.cleanData(getAll(elem)),elem.parentNode&&(keepData&&jQuery.contains(elem.ownerDocument,elem)&&setGlobalEval(getAll(elem,"script")),elem.parentNode.removeChild(elem));return this},empty:function(){for(var elem,i=0;null!=(elem=this[i]);i++)1===elem.nodeType&&(jQuery.cleanData(getAll(elem,!1)),elem.textContent="");return this},clone:function(dataAndEvents,deepDataAndEvents){return dataAndEvents=null==dataAndEvents?!1:dataAndEvents,deepDataAndEvents=null==deepDataAndEvents?dataAndEvents:deepDataAndEvents,this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents)})},html:function(value){return access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(void 0===value&&1===elem.nodeType)return elem.innerHTML;if("string"==typeof value&&!rnoInnerhtml.test(value)&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=value.replace(rxhtmlTag,"<$1>");try{for(;l>i;i++)elem=this[i]||{},1===elem.nodeType&&(jQuery.cleanData(getAll(elem,!1)),elem.innerHTML=value);elem=0}catch(e){}}elem&&this.empty().append(value)},null,value,arguments.length)},replaceWith:function(){var arg=arguments[0];return this.domManip(arguments,function(elem){arg=this.parentNode,jQuery.cleanData(getAll(this)),arg&&arg.replaceChild(elem,this)}),arg&&(arg.length||arg.nodeType)?this:this.remove()},detach:function(selector){return this.remove(selector,!0)},domManip:function(args,callback){args=concat.apply([],args);var fragment,first,scripts,hasScripts,node,doc,i=0,l=this.length,set=this,iNoClone=l-1,value=args[0],isFunction=jQuery.isFunction(value);if(isFunction||l>1&&"string"==typeof value&&!support.checkClone&&rchecked.test(value))return this.each(function(index){var self=set.eq(index);isFunction&&(args[0]=value.call(this,index,self.html())),self.domManip(args,callback)});if(l&&(fragment=jQuery.buildFragment(args,this[0].ownerDocument,!1,this),first=fragment.firstChild,1===fragment.childNodes.length&&(fragment=first),first)){for(scripts=jQuery.map(getAll(fragment,"script"),disableScript),hasScripts=scripts.length;l>i;i++)node=fragment,i!==iNoClone&&(node=jQuery.clone(node,!0,!0),hasScripts&&jQuery.merge(scripts,getAll(node,"script"))),callback.call(this[i],node,i);if(hasScripts)for(doc=scripts[scripts.length-1].ownerDocument,jQuery.map(scripts,restoreScript),i=0;hasScripts>i;i++)node=scripts[i],rscriptType.test(node.type||"")&&!data_priv.access(node,"globalEval")&&jQuery.contains(doc,node)&&(node.src?jQuery._evalUrl&&jQuery._evalUrl(node.src):jQuery.globalEval(node.textContent.replace(rcleanScript,"")))}return this}}),jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(selector){for(var elems,ret=[],insert=jQuery(selector),last=insert.length-1,i=0;last>=i;i++)elems=i===last?this:this.clone(!0),jQuery(insert[i])[original](elems),push.apply(ret,elems.get());return this.pushStack(ret)}});var iframe,elemdisplay={},rmargin=/^margin/,rnumnonpx=new RegExp("^("+pnum+")(?!px)[a-z%]+$","i"),getStyles=function(elem){return elem.ownerDocument.defaultView.getComputedStyle(elem,null)};!function(){function computePixelPositionAndBoxSizingReliable(){div.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",docElem.appendChild(container);var divStyle=window.getComputedStyle(div,null);pixelPositionVal="1%"!==divStyle.top,boxSizingReliableVal="4px"===divStyle.width,docElem.removeChild(container)}var pixelPositionVal,boxSizingReliableVal,divReset="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",docElem=document.documentElement,container=document.createElement("div"),div=document.createElement("div");div.style.backgroundClip="content-box",div.cloneNode(!0).style.backgroundClip="",support.clearCloneStyle="content-box"===div.style.backgroundClip,container.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",container.appendChild(div),window.getComputedStyle&&jQuery.extend(support,{pixelPosition:function(){return computePixelPositionAndBoxSizingReliable(),pixelPositionVal},boxSizingReliable:function(){return null==boxSizingReliableVal&&computePixelPositionAndBoxSizingReliable(),boxSizingReliableVal},reliableMarginRight:function(){var ret,marginDiv=div.appendChild(document.createElement("div"));return marginDiv.style.cssText=div.style.cssText=divReset,marginDiv.style.marginRight=marginDiv.style.width="0",div.style.width="1px",docElem.appendChild(container),ret=!parseFloat(window.getComputedStyle(marginDiv,null).marginRight),docElem.removeChild(container),div.innerHTML="",ret}})}(),jQuery.swap=function(elem,options,callback,args){var ret,name,old={};for(name in options)old[name]=elem.style[name],elem.style[name]=options[name];ret=callback.apply(elem,args||[]);for(name in options)elem.style[name]=old[name];return ret};var rdisplayswap=/^(none|table(?!-c[ea]).+)/,rnumsplit=new RegExp("^("+pnum+")(.*)$","i"),rrelNum=new RegExp("^([+-])=("+pnum+")","i"),cssShow={position:"absolute",visibility:"hidden",display:"block"},cssNormalTransform={letterSpacing:0,fontWeight:400},cssPrefixes=["Webkit","O","Moz","ms"];jQuery.extend({cssHooks:{opacity:{get:function(elem,computed){if(computed){var ret=curCSS(elem,"opacity");return""===ret?"1":ret}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(elem,name,value,extra){if(elem&&3!==elem.nodeType&&8!==elem.nodeType&&elem.style){var ret,type,hooks,origName=jQuery.camelCase(name),style=elem.style;return name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(style,origName)),hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName],void 0===value?hooks&&"get"in hooks&&void 0!==(ret=hooks.get(elem,!1,extra))?ret:style[name]:(type=typeof value,"string"===type&&(ret=rrelNum.exec(value))&&(value=(ret[1]+1)*ret[2]+parseFloat(jQuery.css(elem,name)),type="number"),null!=value&&value===value&&("number"!==type||jQuery.cssNumber[origName]||(value+="px"),support.clearCloneStyle||""!==value||0!==name.indexOf("background")||(style[name]="inherit"),hooks&&"set"in hooks&&void 0===(value=hooks.set(elem,value,extra))||(style[name]="",style[name]=value)),void 0)}},css:function(elem,name,extra,styles){var val,num,hooks,origName=jQuery.camelCase(name);return name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(elem.style,origName)),hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName],hooks&&"get"in hooks&&(val=hooks.get(elem,!0,extra)),void 0===val&&(val=curCSS(elem,name,styles)),"normal"===val&&name in cssNormalTransform&&(val=cssNormalTransform[name]),""===extra||extra?(num=parseFloat(val),extra===!0||jQuery.isNumeric(num)?num||0:val):val}}),jQuery.each(["height","width"],function(i,name){jQuery.cssHooks[name]={get:function(elem,computed,extra){return computed?0===elem.offsetWidth&&rdisplayswap.test(jQuery.css(elem,"display"))?jQuery.swap(elem,cssShow,function(){return getWidthOrHeight(elem,name,extra)}):getWidthOrHeight(elem,name,extra):void 0},set:function(elem,value,extra){var styles=extra&&getStyles(elem);return setPositiveNumber(elem,value,extra?augmentWidthOrHeight(elem,name,extra,"border-box"===jQuery.css(elem,"boxSizing",!1,styles),styles):0)}}}),jQuery.cssHooks.marginRight=addGetHookIf(support.reliableMarginRight,function(elem,computed){return computed?jQuery.swap(elem,{display:"inline-block"},curCSS,[elem,"marginRight"]):void 0}),jQuery.each({margin:"",padding:"",border:"Width"},function(prefix,suffix){jQuery.cssHooks[prefix+suffix]={expand:function(value){for(var i=0,expanded={},parts="string"==typeof value?value.split(" "):[value];4>i;i++)expanded[prefix+cssExpand[i]+suffix]=parts[i]||parts[i-2]||parts[0];return expanded}},rmargin.test(prefix)||(jQuery.cssHooks[prefix+suffix].set=setPositiveNumber)}),jQuery.fn.extend({css:function(name,value){return access(this,function(elem,name,value){var styles,len,map={},i=0;if(jQuery.isArray(name)){for(styles=getStyles(elem),len=name.length;len>i;i++)map[name[i]]=jQuery.css(elem,name[i],!1,styles);return map}return void 0!==value?jQuery.style(elem,name,value):jQuery.css(elem,name)},name,value,arguments.length>1)},show:function(){return showHide(this,!0)},hide:function(){return showHide(this)},toggle:function(state){return"boolean"==typeof state?state?this.show():this.hide():this.each(function(){isHidden(this)?jQuery(this).show():jQuery(this).hide()})}}),jQuery.Tween=Tween,Tween.prototype={constructor:Tween,init:function(elem,options,prop,end,easing,unit){this.elem=elem,this.prop=prop,this.easing=easing||"swing",this.options=options,this.start=this.now=this.cur(),this.end=end,this.unit=unit||(jQuery.cssNumber[prop]?"":"px")},cur:function(){var hooks=Tween.propHooks[this.prop];return hooks&&hooks.get?hooks.get(this):Tween.propHooks._default.get(this)},run:function(percent){var eased,hooks=Tween.propHooks[this.prop];return this.pos=eased=this.options.duration?jQuery.easing[this.easing](percent,this.options.duration*percent,0,1,this.options.duration):percent,this.now=(this.end-this.start)*eased+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),hooks&&hooks.set?hooks.set(this):Tween.propHooks._default.set(this),this}},Tween.prototype.init.prototype=Tween.prototype,Tween.propHooks={_default:{get:function(tween){var result;return null==tween.elem[tween.prop]||tween.elem.style&&null!=tween.elem.style[tween.prop]?(result=jQuery.css(tween.elem,tween.prop,""),result&&"auto"!==result?result:0):tween.elem[tween.prop]},set:function(tween){jQuery.fx.step[tween.prop]?jQuery.fx.step[tween.prop](tween):tween.elem.style&&(null!=tween.elem.style[jQuery.cssProps[tween.prop]]||jQuery.cssHooks[tween.prop])?jQuery.style(tween.elem,tween.prop,tween.now+tween.unit):tween.elem[tween.prop]=tween.now}}},Tween.propHooks.scrollTop=Tween.propHooks.scrollLeft={set:function(tween){tween.elem.nodeType&&tween.elem.parentNode&&(tween.elem[tween.prop]=tween.now)}},jQuery.easing={linear:function(p){return p},swing:function(p){return.5-Math.cos(p*Math.PI)/2}},jQuery.fx=Tween.prototype.init,jQuery.fx.step={};var fxNow,timerId,rfxtypes=/^(?:toggle|show|hide)$/,rfxnum=new RegExp("^(?:([+-])=|)("+pnum+")([a-z%]*)$","i"),rrun=/queueHooks$/,animationPrefilters=[defaultPrefilter],tweeners={"*":[function(prop,value){var tween=this.createTween(prop,value),target=tween.cur(),parts=rfxnum.exec(value),unit=parts&&parts[3]||(jQuery.cssNumber[prop]?"":"px"),start=(jQuery.cssNumber[prop]||"px"!==unit&&+target)&&rfxnum.exec(jQuery.css(tween.elem,prop)),scale=1,maxIterations=20;if(start&&start[3]!==unit){unit=unit||start[3],parts=parts||[],start=+target||1;do scale=scale||".5",start/=scale,jQuery.style(tween.elem,prop,start+unit);while(scale!==(scale=tween.cur()/target)&&1!==scale&&--maxIterations)}return parts&&(start=tween.start=+start||+target||0,tween.unit=unit,tween.end=parts[1]?start+(parts[1]+1)*parts[2]:+parts[2]),tween}]};jQuery.Animation=jQuery.extend(Animation,{tweener:function(props,callback){jQuery.isFunction(props)?(callback=props,props=["*"]):props=props.split(" ");for(var prop,index=0,length=props.length;length>index;index++)prop=props[index],tweeners[prop]=tweeners[prop]||[],tweeners[prop].unshift(callback)},prefilter:function(callback,prepend){prepend?animationPrefilters.unshift(callback):animationPrefilters.push(callback)}}),jQuery.speed=function(speed,easing,fn){var opt=speed&&"object"==typeof speed?jQuery.extend({},speed):{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&!jQuery.isFunction(easing)&&easing};return opt.duration=jQuery.fx.off?0:"number"==typeof opt.duration?opt.duration:opt.duration in jQuery.fx.speeds?jQuery.fx.speeds[opt.duration]:jQuery.fx.speeds._default,(null==opt.queue||opt.queue===!0)&&(opt.queue="fx"),opt.old=opt.complete,opt.complete=function(){jQuery.isFunction(opt.old)&&opt.old.call(this),opt.queue&&jQuery.dequeue(this,opt.queue) -},opt},jQuery.fn.extend({fadeTo:function(speed,to,easing,callback){return this.filter(isHidden).css("opacity",0).show().end().animate({opacity:to},speed,easing,callback)},animate:function(prop,speed,easing,callback){var empty=jQuery.isEmptyObject(prop),optall=jQuery.speed(speed,easing,callback),doAnimation=function(){var anim=Animation(this,jQuery.extend({},prop),optall);(empty||data_priv.get(this,"finish"))&&anim.stop(!0)};return doAnimation.finish=doAnimation,empty||optall.queue===!1?this.each(doAnimation):this.queue(optall.queue,doAnimation)},stop:function(type,clearQueue,gotoEnd){var stopQueue=function(hooks){var stop=hooks.stop;delete hooks.stop,stop(gotoEnd)};return"string"!=typeof type&&(gotoEnd=clearQueue,clearQueue=type,type=void 0),clearQueue&&type!==!1&&this.queue(type||"fx",[]),this.each(function(){var dequeue=!0,index=null!=type&&type+"queueHooks",timers=jQuery.timers,data=data_priv.get(this);if(index)data[index]&&data[index].stop&&stopQueue(data[index]);else for(index in data)data[index]&&data[index].stop&&rrun.test(index)&&stopQueue(data[index]);for(index=timers.length;index--;)timers[index].elem!==this||null!=type&&timers[index].queue!==type||(timers[index].anim.stop(gotoEnd),dequeue=!1,timers.splice(index,1));(dequeue||!gotoEnd)&&jQuery.dequeue(this,type)})},finish:function(type){return type!==!1&&(type=type||"fx"),this.each(function(){var index,data=data_priv.get(this),queue=data[type+"queue"],hooks=data[type+"queueHooks"],timers=jQuery.timers,length=queue?queue.length:0;for(data.finish=!0,jQuery.queue(this,type,[]),hooks&&hooks.stop&&hooks.stop.call(this,!0),index=timers.length;index--;)timers[index].elem===this&&timers[index].queue===type&&(timers[index].anim.stop(!0),timers.splice(index,1));for(index=0;length>index;index++)queue[index]&&queue[index].finish&&queue[index].finish.call(this);delete data.finish})}}),jQuery.each(["toggle","show","hide"],function(i,name){var cssFn=jQuery.fn[name];jQuery.fn[name]=function(speed,easing,callback){return null==speed||"boolean"==typeof speed?cssFn.apply(this,arguments):this.animate(genFx(name,!0),speed,easing,callback)}}),jQuery.each({slideDown:genFx("show"),slideUp:genFx("hide"),slideToggle:genFx("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(name,props){jQuery.fn[name]=function(speed,easing,callback){return this.animate(props,speed,easing,callback)}}),jQuery.timers=[],jQuery.fx.tick=function(){var timer,i=0,timers=jQuery.timers;for(fxNow=jQuery.now();i1)},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name)})}}),jQuery.extend({attr:function(elem,name,value){var hooks,ret,nType=elem.nodeType;if(elem&&3!==nType&&8!==nType&&2!==nType)return typeof elem.getAttribute===strundefined?jQuery.prop(elem,name,value):(1===nType&&jQuery.isXMLDoc(elem)||(name=name.toLowerCase(),hooks=jQuery.attrHooks[name]||(jQuery.expr.match.bool.test(name)?boolHook:nodeHook)),void 0===value?hooks&&"get"in hooks&&null!==(ret=hooks.get(elem,name))?ret:(ret=jQuery.find.attr(elem,name),null==ret?void 0:ret):null!==value?hooks&&"set"in hooks&&void 0!==(ret=hooks.set(elem,value,name))?ret:(elem.setAttribute(name,value+""),value):void jQuery.removeAttr(elem,name))},removeAttr:function(elem,value){var name,propName,i=0,attrNames=value&&value.match(rnotwhite);if(attrNames&&1===elem.nodeType)for(;name=attrNames[i++];)propName=jQuery.propFix[name]||name,jQuery.expr.match.bool.test(name)&&(elem[propName]=!1),elem.removeAttribute(name)},attrHooks:{type:{set:function(elem,value){if(!support.radioValue&&"radio"===value&&jQuery.nodeName(elem,"input")){var val=elem.value;return elem.setAttribute("type",value),val&&(elem.value=val),value}}}}}),boolHook={set:function(elem,value,name){return value===!1?jQuery.removeAttr(elem,name):elem.setAttribute(name,name),name}},jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g),function(i,name){var getter=attrHandle[name]||jQuery.find.attr;attrHandle[name]=function(elem,name,isXML){var ret,handle;return isXML||(handle=attrHandle[name],attrHandle[name]=ret,ret=null!=getter(elem,name,isXML)?name.toLowerCase():null,attrHandle[name]=handle),ret}});var rfocusable=/^(?:input|select|textarea|button)$/i;jQuery.fn.extend({prop:function(name,value){return access(this,jQuery.prop,name,value,arguments.length>1)},removeProp:function(name){return this.each(function(){delete this[jQuery.propFix[name]||name]})}}),jQuery.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(elem,name,value){var ret,hooks,notxml,nType=elem.nodeType;if(elem&&3!==nType&&8!==nType&&2!==nType)return notxml=1!==nType||!jQuery.isXMLDoc(elem),notxml&&(name=jQuery.propFix[name]||name,hooks=jQuery.propHooks[name]),void 0!==value?hooks&&"set"in hooks&&void 0!==(ret=hooks.set(elem,value,name))?ret:elem[name]=value:hooks&&"get"in hooks&&null!==(ret=hooks.get(elem,name))?ret:elem[name]},propHooks:{tabIndex:{get:function(elem){return elem.hasAttribute("tabindex")||rfocusable.test(elem.nodeName)||elem.href?elem.tabIndex:-1}}}}),support.optSelected||(jQuery.propHooks.selected={get:function(elem){var parent=elem.parentNode;return parent&&parent.parentNode&&parent.parentNode.selectedIndex,null}}),jQuery.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){jQuery.propFix[this.toLowerCase()]=this});var rclass=/[\t\r\n\f]/g;jQuery.fn.extend({addClass:function(value){var classes,elem,cur,clazz,j,finalValue,proceed="string"==typeof value&&value,i=0,len=this.length;if(jQuery.isFunction(value))return this.each(function(j){jQuery(this).addClass(value.call(this,j,this.className))});if(proceed)for(classes=(value||"").match(rnotwhite)||[];len>i;i++)if(elem=this[i],cur=1===elem.nodeType&&(elem.className?(" "+elem.className+" ").replace(rclass," "):" ")){for(j=0;clazz=classes[j++];)cur.indexOf(" "+clazz+" ")<0&&(cur+=clazz+" ");finalValue=jQuery.trim(cur),elem.className!==finalValue&&(elem.className=finalValue)}return this},removeClass:function(value){var classes,elem,cur,clazz,j,finalValue,proceed=0===arguments.length||"string"==typeof value&&value,i=0,len=this.length;if(jQuery.isFunction(value))return this.each(function(j){jQuery(this).removeClass(value.call(this,j,this.className))});if(proceed)for(classes=(value||"").match(rnotwhite)||[];len>i;i++)if(elem=this[i],cur=1===elem.nodeType&&(elem.className?(" "+elem.className+" ").replace(rclass," "):"")){for(j=0;clazz=classes[j++];)for(;cur.indexOf(" "+clazz+" ")>=0;)cur=cur.replace(" "+clazz+" "," ");finalValue=value?jQuery.trim(cur):"",elem.className!==finalValue&&(elem.className=finalValue)}return this},toggleClass:function(value,stateVal){var type=typeof value;return"boolean"==typeof stateVal&&"string"===type?stateVal?this.addClass(value):this.removeClass(value):this.each(jQuery.isFunction(value)?function(i){jQuery(this).toggleClass(value.call(this,i,this.className,stateVal),stateVal)}:function(){if("string"===type)for(var className,i=0,self=jQuery(this),classNames=value.match(rnotwhite)||[];className=classNames[i++];)self.hasClass(className)?self.removeClass(className):self.addClass(className);else(type===strundefined||"boolean"===type)&&(this.className&&data_priv.set(this,"__className__",this.className),this.className=this.className||value===!1?"":data_priv.get(this,"__className__")||"")})},hasClass:function(selector){for(var className=" "+selector+" ",i=0,l=this.length;l>i;i++)if(1===this[i].nodeType&&(" "+this[i].className+" ").replace(rclass," ").indexOf(className)>=0)return!0;return!1}});var rreturn=/\r/g;jQuery.fn.extend({val:function(value){var hooks,ret,isFunction,elem=this[0];{if(arguments.length)return isFunction=jQuery.isFunction(value),this.each(function(i){var val;1===this.nodeType&&(val=isFunction?value.call(this,i,jQuery(this).val()):value,null==val?val="":"number"==typeof val?val+="":jQuery.isArray(val)&&(val=jQuery.map(val,function(value){return null==value?"":value+""})),hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()],hooks&&"set"in hooks&&void 0!==hooks.set(this,val,"value")||(this.value=val))});if(elem)return hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()],hooks&&"get"in hooks&&void 0!==(ret=hooks.get(elem,"value"))?ret:(ret=elem.value,"string"==typeof ret?ret.replace(rreturn,""):null==ret?"":ret)}}}),jQuery.extend({valHooks:{select:{get:function(elem){for(var value,option,options=elem.options,index=elem.selectedIndex,one="select-one"===elem.type||0>index,values=one?null:[],max=one?index+1:options.length,i=0>index?max:one?index:0;max>i;i++)if(option=options[i],!(!option.selected&&i!==index||(support.optDisabled?option.disabled:null!==option.getAttribute("disabled"))||option.parentNode.disabled&&jQuery.nodeName(option.parentNode,"optgroup"))){if(value=jQuery(option).val(),one)return value;values.push(value)}return values},set:function(elem,value){for(var optionSet,option,options=elem.options,values=jQuery.makeArray(value),i=options.length;i--;)option=options[i],(option.selected=jQuery.inArray(jQuery(option).val(),values)>=0)&&(optionSet=!0);return optionSet||(elem.selectedIndex=-1),values}}}}),jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]={set:function(elem,value){return jQuery.isArray(value)?elem.checked=jQuery.inArray(jQuery(elem).val(),value)>=0:void 0}},support.checkOn||(jQuery.valHooks[this].get=function(elem){return null===elem.getAttribute("value")?"on":elem.value})}),jQuery.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(i,name){jQuery.fn[name]=function(data,fn){return arguments.length>0?this.on(name,null,data,fn):this.trigger(name)}}),jQuery.fn.extend({hover:function(fnOver,fnOut){return this.mouseenter(fnOver).mouseleave(fnOut||fnOver)},bind:function(types,data,fn){return this.on(types,null,data,fn)},unbind:function(types,fn){return this.off(types,null,fn)},delegate:function(selector,types,data,fn){return this.on(types,selector,data,fn)},undelegate:function(selector,types,fn){return 1===arguments.length?this.off(selector,"**"):this.off(types,selector||"**",fn)}});var nonce=jQuery.now(),rquery=/\?/;jQuery.parseJSON=function(data){return JSON.parse(data+"")},jQuery.parseXML=function(data){var xml,tmp;if(!data||"string"!=typeof data)return null;try{tmp=new DOMParser,xml=tmp.parseFromString(data,"text/xml")}catch(e){xml=void 0}return(!xml||xml.getElementsByTagName("parsererror").length)&&jQuery.error("Invalid XML: "+data),xml};var ajaxLocParts,ajaxLocation,rhash=/#.*$/,rts=/([?&])_=[^&]*/,rheaders=/^(.*?):[ \t]*([^\r\n]*)$/gm,rlocalProtocol=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,rnoContent=/^(?:GET|HEAD)$/,rprotocol=/^\/\//,rurl=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,prefilters={},transports={},allTypes="*/".concat("*");try{ajaxLocation=location.href}catch(e){ajaxLocation=document.createElement("a"),ajaxLocation.href="",ajaxLocation=ajaxLocation.href}ajaxLocParts=rurl.exec(ajaxLocation.toLowerCase())||[],jQuery.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ajaxLocation,type:"GET",isLocal:rlocalProtocol.test(ajaxLocParts[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":allTypes,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":jQuery.parseJSON,"text xml":jQuery.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(target,settings){return settings?ajaxExtend(ajaxExtend(target,jQuery.ajaxSettings),settings):ajaxExtend(jQuery.ajaxSettings,target)},ajaxPrefilter:addToPrefiltersOrTransports(prefilters),ajaxTransport:addToPrefiltersOrTransports(transports),ajax:function(url,options){function done(status,nativeStatusText,responses,headers){var isSuccess,success,error,response,modified,statusText=nativeStatusText;2!==state&&(state=2,timeoutTimer&&clearTimeout(timeoutTimer),transport=void 0,responseHeadersString=headers||"",jqXHR.readyState=status>0?4:0,isSuccess=status>=200&&300>status||304===status,responses&&(response=ajaxHandleResponses(s,jqXHR,responses)),response=ajaxConvert(s,response,jqXHR,isSuccess),isSuccess?(s.ifModified&&(modified=jqXHR.getResponseHeader("Last-Modified"),modified&&(jQuery.lastModified[cacheURL]=modified),modified=jqXHR.getResponseHeader("etag"),modified&&(jQuery.etag[cacheURL]=modified)),204===status||"HEAD"===s.type?statusText="nocontent":304===status?statusText="notmodified":(statusText=response.state,success=response.data,error=response.error,isSuccess=!error)):(error=statusText,(status||!statusText)&&(statusText="error",0>status&&(status=0))),jqXHR.status=status,jqXHR.statusText=(nativeStatusText||statusText)+"",isSuccess?deferred.resolveWith(callbackContext,[success,statusText,jqXHR]):deferred.rejectWith(callbackContext,[jqXHR,statusText,error]),jqXHR.statusCode(statusCode),statusCode=void 0,fireGlobals&&globalEventContext.trigger(isSuccess?"ajaxSuccess":"ajaxError",[jqXHR,s,isSuccess?success:error]),completeDeferred.fireWith(callbackContext,[jqXHR,statusText]),fireGlobals&&(globalEventContext.trigger("ajaxComplete",[jqXHR,s]),--jQuery.active||jQuery.event.trigger("ajaxStop")))}"object"==typeof url&&(options=url,url=void 0),options=options||{};var transport,cacheURL,responseHeadersString,responseHeaders,timeoutTimer,parts,fireGlobals,i,s=jQuery.ajaxSetup({},options),callbackContext=s.context||s,globalEventContext=s.context&&(callbackContext.nodeType||callbackContext.jquery)?jQuery(callbackContext):jQuery.event,deferred=jQuery.Deferred(),completeDeferred=jQuery.Callbacks("once memory"),statusCode=s.statusCode||{},requestHeaders={},requestHeadersNames={},state=0,strAbort="canceled",jqXHR={readyState:0,getResponseHeader:function(key){var match;if(2===state){if(!responseHeaders)for(responseHeaders={};match=rheaders.exec(responseHeadersString);)responseHeaders[match[1].toLowerCase()]=match[2];match=responseHeaders[key.toLowerCase()]}return null==match?null:match},getAllResponseHeaders:function(){return 2===state?responseHeadersString:null},setRequestHeader:function(name,value){var lname=name.toLowerCase();return state||(name=requestHeadersNames[lname]=requestHeadersNames[lname]||name,requestHeaders[name]=value),this},overrideMimeType:function(type){return state||(s.mimeType=type),this},statusCode:function(map){var code;if(map)if(2>state)for(code in map)statusCode[code]=[statusCode[code],map[code]];else jqXHR.always(map[jqXHR.status]);return this},abort:function(statusText){var finalText=statusText||strAbort;return transport&&transport.abort(finalText),done(0,finalText),this}};if(deferred.promise(jqXHR).complete=completeDeferred.add,jqXHR.success=jqXHR.done,jqXHR.error=jqXHR.fail,s.url=((url||s.url||ajaxLocation)+"").replace(rhash,"").replace(rprotocol,ajaxLocParts[1]+"//"),s.type=options.method||options.type||s.method||s.type,s.dataTypes=jQuery.trim(s.dataType||"*").toLowerCase().match(rnotwhite)||[""],null==s.crossDomain&&(parts=rurl.exec(s.url.toLowerCase()),s.crossDomain=!(!parts||parts[1]===ajaxLocParts[1]&&parts[2]===ajaxLocParts[2]&&(parts[3]||("http:"===parts[1]?"80":"443"))===(ajaxLocParts[3]||("http:"===ajaxLocParts[1]?"80":"443")))),s.data&&s.processData&&"string"!=typeof s.data&&(s.data=jQuery.param(s.data,s.traditional)),inspectPrefiltersOrTransports(prefilters,s,options,jqXHR),2===state)return jqXHR;fireGlobals=s.global,fireGlobals&&0===jQuery.active++&&jQuery.event.trigger("ajaxStart"),s.type=s.type.toUpperCase(),s.hasContent=!rnoContent.test(s.type),cacheURL=s.url,s.hasContent||(s.data&&(cacheURL=s.url+=(rquery.test(cacheURL)?"&":"?")+s.data,delete s.data),s.cache===!1&&(s.url=rts.test(cacheURL)?cacheURL.replace(rts,"$1_="+nonce++):cacheURL+(rquery.test(cacheURL)?"&":"?")+"_="+nonce++)),s.ifModified&&(jQuery.lastModified[cacheURL]&&jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[cacheURL]),jQuery.etag[cacheURL]&&jqXHR.setRequestHeader("If-None-Match",jQuery.etag[cacheURL])),(s.data&&s.hasContent&&s.contentType!==!1||options.contentType)&&jqXHR.setRequestHeader("Content-Type",s.contentType),jqXHR.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+("*"!==s.dataTypes[0]?", "+allTypes+"; q=0.01":""):s.accepts["*"]);for(i in s.headers)jqXHR.setRequestHeader(i,s.headers[i]);if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===!1||2===state))return jqXHR.abort();strAbort="abort";for(i in{success:1,error:1,complete:1})jqXHR[i](s[i]);if(transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR)){jqXHR.readyState=1,fireGlobals&&globalEventContext.trigger("ajaxSend",[jqXHR,s]),s.async&&s.timeout>0&&(timeoutTimer=setTimeout(function(){jqXHR.abort("timeout")},s.timeout));try{state=1,transport.send(requestHeaders,done)}catch(e){if(!(2>state))throw e;done(-1,e)}}else done(-1,"No Transport");return jqXHR},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json")},getScript:function(url,callback){return jQuery.get(url,void 0,callback,"script")}}),jQuery.each(["get","post"],function(i,method){jQuery[method]=function(url,data,callback,type){return jQuery.isFunction(data)&&(type=type||callback,callback=data,data=void 0),jQuery.ajax({url:url,type:method,dataType:type,data:data,success:callback})}}),jQuery.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(i,type){jQuery.fn[type]=function(fn){return this.on(type,fn)}}),jQuery._evalUrl=function(url){return jQuery.ajax({url:url,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},jQuery.fn.extend({wrapAll:function(html){var wrap;return jQuery.isFunction(html)?this.each(function(i){jQuery(this).wrapAll(html.call(this,i))}):(this[0]&&(wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&wrap.insertBefore(this[0]),wrap.map(function(){for(var elem=this;elem.firstElementChild;)elem=elem.firstElementChild;return elem}).append(this)),this)},wrapInner:function(html){return this.each(jQuery.isFunction(html)?function(i){jQuery(this).wrapInner(html.call(this,i))}:function(){var self=jQuery(this),contents=self.contents();contents.length?contents.wrapAll(html):self.append(html)})},wrap:function(html){var isFunction=jQuery.isFunction(html);return this.each(function(i){jQuery(this).wrapAll(isFunction?html.call(this,i):html)})},unwrap:function(){return this.parent().each(function(){jQuery.nodeName(this,"body")||jQuery(this).replaceWith(this.childNodes)}).end()}}),jQuery.expr.filters.hidden=function(elem){return elem.offsetWidth<=0&&elem.offsetHeight<=0},jQuery.expr.filters.visible=function(elem){return!jQuery.expr.filters.hidden(elem)};var r20=/%20/g,rbracket=/\[\]$/,rCRLF=/\r?\n/g,rsubmitterTypes=/^(?:submit|button|image|reset|file)$/i,rsubmittable=/^(?:input|select|textarea|keygen)/i;jQuery.param=function(a,traditional){var prefix,s=[],add=function(key,value){value=jQuery.isFunction(value)?value():null==value?"":value,s[s.length]=encodeURIComponent(key)+"="+encodeURIComponent(value)};if(void 0===traditional&&(traditional=jQuery.ajaxSettings&&jQuery.ajaxSettings.traditional),jQuery.isArray(a)||a.jquery&&!jQuery.isPlainObject(a))jQuery.each(a,function(){add(this.name,this.value)});else for(prefix in a)buildParams(prefix,a[prefix],traditional,add);return s.join("&").replace(r20,"+")},jQuery.fn.extend({serialize:function(){return jQuery.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var elements=jQuery.prop(this,"elements");return elements?jQuery.makeArray(elements):this}).filter(function(){var type=this.type;return this.name&&!jQuery(this).is(":disabled")&&rsubmittable.test(this.nodeName)&&!rsubmitterTypes.test(type)&&(this.checked||!rcheckableType.test(type))}).map(function(i,elem){var val=jQuery(this).val();return null==val?null:jQuery.isArray(val)?jQuery.map(val,function(val){return{name:elem.name,value:val.replace(rCRLF,"\r\n")}}):{name:elem.name,value:val.replace(rCRLF,"\r\n")}}).get()}}),jQuery.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(e){}};var xhrId=0,xhrCallbacks={},xhrSuccessStatus={0:200,1223:204},xhrSupported=jQuery.ajaxSettings.xhr();window.ActiveXObject&&jQuery(window).on("unload",function(){for(var key in xhrCallbacks)xhrCallbacks[key]()}),support.cors=!!xhrSupported&&"withCredentials"in xhrSupported,support.ajax=xhrSupported=!!xhrSupported,jQuery.ajaxTransport(function(options){var callback;return support.cors||xhrSupported&&!options.crossDomain?{send:function(headers,complete){var i,xhr=options.xhr(),id=++xhrId;if(xhr.open(options.type,options.url,options.async,options.username,options.password),options.xhrFields)for(i in options.xhrFields)xhr[i]=options.xhrFields[i];options.mimeType&&xhr.overrideMimeType&&xhr.overrideMimeType(options.mimeType),options.crossDomain||headers["X-Requested-With"]||(headers["X-Requested-With"]="XMLHttpRequest");for(i in headers)xhr.setRequestHeader(i,headers[i]);callback=function(type){return function(){callback&&(delete xhrCallbacks[id],callback=xhr.onload=xhr.onerror=null,"abort"===type?xhr.abort():"error"===type?complete(xhr.status,xhr.statusText):complete(xhrSuccessStatus[xhr.status]||xhr.status,xhr.statusText,"string"==typeof xhr.responseText?{text:xhr.responseText}:void 0,xhr.getAllResponseHeaders()))}},xhr.onload=callback(),xhr.onerror=callback("error"),callback=xhrCallbacks[id]=callback("abort"),xhr.send(options.hasContent&&options.data||null)},abort:function(){callback&&callback()}}:void 0}),jQuery.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(text){return jQuery.globalEval(text),text}}}),jQuery.ajaxPrefilter("script",function(s){void 0===s.cache&&(s.cache=!1),s.crossDomain&&(s.type="GET")}),jQuery.ajaxTransport("script",function(s){if(s.crossDomain){var script,callback;return{send:function(_,complete){script=jQuery(" + @@ -118,7 +119,7 @@ - + diff --git a/app/scripts/services/imagecropmodal.js b/app/scripts/controllers/imagecropmodal.js similarity index 91% rename from app/scripts/services/imagecropmodal.js rename to app/scripts/controllers/imagecropmodal.js index fbf3e2640..ed6765de2 100644 --- a/app/scripts/services/imagecropmodal.js +++ b/app/scripts/controllers/imagecropmodal.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('bulbsCmsApp') - .value('ModalInstanceCtrl', function ($scope, $timeout, $modalInstance, BettyCropper, id) { + .controller('ImageCropModalCtrl', function ($scope, $timeout, $modalInstance, BettyCropper, id) { $scope.cropMode = false; $scope.thumb = {height:180, width: 180}; $scope.preview_thumb = {height: 110, width: 110}; @@ -191,19 +191,4 @@ angular.module('bulbsCmsApp') $scope.onInit(); - }) - .factory('openImageCropModal', function ($window, $modal, routes, ModalInstanceCtrl) { - var openImageCropModal = function (id) { - - return $modal.open({ - templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", - controller: ModalInstanceCtrl, - resolve: { - id: function () { return id; } - } - }).result; - - }; - $window.openImageCropModal = openImageCropModal; // THIS IS SOME BULLSHIT - return openImageCropModal; - }) + }); \ No newline at end of file diff --git a/app/scripts/directives/titleimage.js b/app/scripts/directives/titleimage.js index 356ab8527..c8f3bef7a 100644 --- a/app/scripts/directives/titleimage.js +++ b/app/scripts/directives/titleimage.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('bulbsCmsApp') - .directive('titleimage', function ($http, $window, $, routes, openImageCropModal) { + .directive('titleimage', function ($http, $window, $, routes) { return { restrict: 'E', templateUrl: routes.PARTIALS_URL + 'titleimage.html', @@ -42,8 +42,30 @@ angular.module('bulbsCmsApp') }); }, scope.editTitleImage = function () { - openImageCropModal(scope.image.id).then( - function () { + $window.openImageDrawer( + scope.image.id, + function (data) { + function removeLoadingGif() { + $element.find('.image img[src=\"' + routes.LOADING_IMG_SRC + '\"]').remove(); + } + + removeLoadingGif(); + + if ($element.find('.image').data('imageId') === data.id) { + return; + } + + $element.find('.image img').on('load', removeLoadingGif); + $element.find('.image img').after(''); + + scope.image.id = data.id.toString(); + scope.$apply(); + $window.picturefill(); + if ($element.find('.image img')[0].complete) { removeLoadingGif(); } + }, + function () { return; }, + function (oldImage) { + scope.image = oldImage; $window.picturefill(); } ); diff --git a/app/scripts/services/openimagecropmodal.js b/app/scripts/services/openimagecropmodal.js new file mode 100644 index 000000000..9c0ad79e6 --- /dev/null +++ b/app/scripts/services/openimagecropmodal.js @@ -0,0 +1,18 @@ +'use strict'; + +angular.module('bulbsCmsApp') + .factory('openImageCropModal', function ($window, $modal, routes) { + var openImageCropModal = function (id) { + + return $modal.open({ + templateUrl: routes.PARTIALS_URL + "image-crop-modal.html", + controller: 'ImageCropModalCtrl', + resolve: { + id: function () { return id; } + } + }).result; + + }; + $window.openImageCropModal = openImageCropModal; // for editor inline images + return openImageCropModal; + }); diff --git a/app/styles/main.less b/app/styles/main.less index b7e11f59b..e3eba3082 100644 --- a/app/styles/main.less +++ b/app/styles/main.less @@ -212,3 +212,90 @@ nav.navbar{ .close { margin-top: 5px; } } #targeting .panel-heading, #pzone-content .panel-heading { cursor: default; } + +.image-cropper-modal { + .modal-body { + .breather { + padding-top: 20px; + } + .more-breathing { + padding-bottom: 20px + } + .thumb-list { + li { + display: inline-block; + height: 180px; + width: 180px; + margin: 0 3px; + position: relative; + &.preview_thumb { + height: 110px; + width: 110px; + .crop-overlay { + display: block; + background: rgba(0, 0, 0, 0.6); + .overlay-text { + font-size: 20px; + display: block; + } + } + } + &:hover .crop-overlay { + background: rgba(0, 0, 0, 0.6); + .overlay-text { display: block; } + } + .crop-overlay { + position: absolute; + z-index: 2; + top: 0; left: 0; right: 0; bottom: 0; + .overlay-text { + display: none; + color: white; + position: absolute; + top: 0; left: 0; right: 0; bottom: 0; + margin: auto; + text-align: center; + height: 64px; + font-size: 40px; + } + } + .cropped-thumb { + overflow: hidden; + position: absolute; + top: 0; left: 0; right: 0; bottom: 0; + margin: 0 auto; + } + } + } + .actions { + text-align: center; + button { + width: 100%; + margin-bottom: 5px; + } + } + .ratio-paginator span.fa-circle { + margin: 0 8px; + color: #dedede; + } + } +} + +.edit-page bettyeditable .image-edit-container { + padding: 10px; + .edit { + bottom: auto; + top: 10px; + } + .remove { + bottom: auto; + top: 10px; + } + .caption-alt { + position: absolute; + bottom: 0px; + left: 10px; + width: 101%; + } +} + diff --git a/test/spec/controllers/imagecropmodalctrl.js b/test/spec/controllers/imagecropmodalctrl.js index 2689f532c..6ff372e09 100644 --- a/test/spec/controllers/imagecropmodalctrl.js +++ b/test/spec/controllers/imagecropmodalctrl.js @@ -1,12 +1,12 @@ 'use strict'; -describe('Controller: ModalInstanceCtrl', function () { +describe('Controller: ImageCropModalCtrl', function () { // load the controller's module beforeEach(module('bulbsCmsApp')); beforeEach(module('bulbsCmsApp.mockApi')); - var $httpBackend, $rootScope, ModalInstanceCtrl, + var $httpBackend, $rootScope, ImageCropModalCtrl, modalInstance, scope, mockApiData, BettyCropper; // Initialize the controller and a mock scope @@ -37,8 +37,8 @@ describe('Controller: ModalInstanceCtrl', function () { scope = $rootScope.$new(); - ModalInstanceCtrl = $controller( - $injector.get('ModalInstanceCtrl'), + ImageCropModalCtrl = $controller( + 'ImageCropModalCtrl', { $scope: scope, $modalInstance: modalInstance, From de59700300282610074dd7fc0411f332cf348417 Mon Sep 17 00:00:00 2001 From: Shaker Islam Date: Thu, 8 May 2014 16:48:14 -0500 Subject: [PATCH 26/27] adding image.js for backwards compatibility --- app/image.js | 228 +++++++++++++++++++++++++++++++++++++++++++++++++ app/index.html | 2 +- 2 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 app/image.js diff --git a/app/image.js b/app/image.js new file mode 100644 index 000000000..b716bd5ce --- /dev/null +++ b/app/image.js @@ -0,0 +1,228 @@ +(function( w ){ + /* We can request an image at every possible width, but let's limit it to a reasonable number + We can set these so they correspond to our more common sizes. + */ + + var breakpoints = [0, 80, 150, 240, 300, 320, 400, 480, 620, 640, 820, 960, 1200, 1600]; + function tmpl(text, dict) { + for (var k in dict) { + text = text.replace("{{" + k + "}}", dict[k]); + } + return text; + } + w.picturefill = function() { + //don't need to do them all at once. can decide to do lazy load if needed + var ps = w.document.getElementsByTagName( "div" ); + var imageData = []; + for( var i = 0, il = ps.length; i < il; i++ ){ + var el = ps[i]; + if(el.getAttribute( "data-type" ) !== "image" ){ + continue; + } + var div = el.getElementsByTagName( "div" )[0]; + if( el.getAttribute( "data-image-id" ) !== null ){ + var id = el.getAttribute( "data-image-id" ), + crop = el.getAttribute( "data-crop" ); + var _w = div.offsetWidth, + _h = div.offsetHeight; + + if (!crop || crop === "" || crop === "auto") { + crop = computeAspectRatio(_w, _h); + } + if (el.getAttribute("data-format")) { + format = el.getAttribute("data-format"); + } + else { + format = "jpg"; + } + + var width = 50; + for (var j = 0; j < breakpoints.length; j++) { + if (_w <= breakpoints[j]) { + width = breakpoints[j]; + break; + } + } + // TODO: do something for retina + if (w.devicePixelRatio) { + if (w.devicePixelRatio > 1) { + + } + } + + // Find any existing img element in the picture element + var picImg = div.getElementsByTagName( "img" )[ 0 ]; + + if(!picImg){ + // for performance reasons this will be added to the dom later + picImg = w.document.createElement( "img" ); + picImg.alt = el.getAttribute( "data-alt" ); + } + + //picImg.className = "loading"; + picImg.onload = function() { + //this.className = ""; + }; + // if the existing image is larger (or the same) than the one we're about to load, do not update. + //however if the crop changes, we need to reload. + if (width > 0) { + + //ie8 doesn't support natural width, always load. + if (typeof picImg.naturalWidth === "undefined" || picImg.naturalWidth < width || + crop !== computeAspectRatio(picImg.naturalWidth, picImg.naturalHeight)) { + var id_str = ""; + for(var ii=0; ii < id.length; ii++) { + if ((ii % 4) === 0) { + id_str += "/"; + } + id_str += id.charAt(ii); + } + var url = tmpl(w.IMAGE_URL, {id: id_str, crop: crop, width: width, format:format}); + imageData.push({ + 'div': div, + 'img': picImg, + 'url': url + }); + } + } + } + } + // all DOM updates should probably go here + for(var i = 0; i < imageData.length; i++) { + var data = imageData[i]; + data.img.src = data.url; + if (!data.img.parentNode) { + data.div.appendChild(data.img); + } + } + }; + + function computeAspectRatio(_w, _h) { + if (_w !== 0 && _h !== 0) { + var aspectRatio = Math.ceil(_w/_h * 10); + //smooth out rounding issues. + switch (aspectRatio) { + case 30: + case 31: + crop = "3x1"; + break; + case 20: + crop = "2x1"; + break; + case 14: + crop = "4x3"; + break; + case 18: + crop = "16x9"; + break; + case 8: + crop = "3x4"; + break; + case 10: + crop = "1x1"; + break; + default: + crop = "original"; + } + return crop; + } + else { + return "16x9" + } + } + + // NOTE: this is used elsewhere so I'm putting it back in for now. + w.pictureFillElement = function(el) { + var div = el.getElementsByTagName( "div" )[0]; + + if( el.getAttribute( "data-image-id" ) !== null ){ + var id = el.getAttribute( "data-image-id" ), + crop = el.getAttribute( "data-crop" ); + var _w = div.offsetWidth, + _h = div.offsetHeight; + + + if (!crop || crop === "" || crop === "auto") { + crop = computeAspectRatio(_w, _h); + } + if (el.getAttribute("data-format")) { + format = el.getAttribute("data-format"); + } + else { + format = "jpg"; + } + + + var width = 50; + for (var j = 0; j < breakpoints.length; j++) { + if (_w <= breakpoints[j]) { + width = breakpoints[j]; + break; + } + } + // TODO: do something for retina + if (w.devicePixelRatio) { + if (w.devicePixelRatio > 1) { + + } + } + + // Find any existing img element in the picture element + var picImg = div.getElementsByTagName( "img" )[ 0 ]; + + + if(!picImg){ + picImg = w.document.createElement( "img" ); + picImg.alt = el.getAttribute( "data-alt" ); + + div.appendChild( picImg ); + } + + //picImg.className = "loading"; + picImg.onload = function() { + //this.className = ""; + }; + // if the existing image is larger (or the same) than the one we're about to load, do not update. + //however if the crop changes, we need to reload. + if (width > 0) { + + //ie8 doesn't support natuarl width, always load. + if (typeof picImg.naturalWidth === "undefined" || picImg.naturalWidth < width || + crop !== computeAspectRatio(picImg.naturalWidth, picImg.naturalHeight)) { + var id_str = ""; + for(var i=0;i < id.length;i++) { + if ((i % 4) === 0) { + id_str += "/"; + } + id_str += id.charAt(i); + } + var url = tmpl(w.IMAGE_URL, {id: id_str, crop: crop, width: width, format:format}); + picImg.src = url; + } + } + } + }; + + // Run on resize and domready (w.load as a fallback) + if (!w.IMAGE_LISTENERS_DISABLED) { + if( w.addEventListener ){ + var pictureFillTimeout; + w.addEventListener( "resize", + function() { + clearTimeout(pictureFillTimeout); + pictureFillTimeout = setTimeout(w.picturefill, 100); + }, false ); + + w.addEventListener( "DOMContentLoaded", function(){ + w.picturefill(); + // Run once only + w.removeEventListener( "load", w.picturefill, false ); + }, false ); + w.addEventListener( "load", w.picturefill, false ); + + } + else if( w.attachEvent ){ + w.attachEvent( "onload", w.picturefill ); + } + } +}( this )); \ No newline at end of file diff --git a/app/index.html b/app/index.html index 25c3bef31..dccbae2d7 100644 --- a/app/index.html +++ b/app/index.html @@ -27,7 +27,7 @@ - +