Start on tour infrastructure. Note that this code works but is NOT STYLED and has a FAKE TEMP TOUR in it

This commit is contained in:
Joseph Schorr 2014-02-04 20:50:13 -05:00
parent 37507b7d7d
commit a049fc57c6
10 changed files with 411 additions and 130 deletions

View file

@ -103,8 +103,8 @@ function getMarkedDown(string) {
}
// Start the application code itself.
quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'restangular', 'angularMoment', 'angulartics', /*'angulartics.google.analytics',*/ 'angulartics.mixpanel', '$strap.directives', 'ngCookies', 'ngSanitize', 'angular-md5'], function($provide, cfpLoadingBarProvider) {
cfpLoadingBarProvider.includeSpinner = false;
quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'angular-tour', 'restangular', 'angularMoment', 'angulartics', /*'angulartics.google.analytics',*/ 'angulartics.mixpanel', '$strap.directives', 'ngCookies', 'ngSanitize', 'angular-md5'], function($provide, cfpLoadingBarProvider) {
cfpLoadingBarProvider.includeSpinner = false;
$provide.factory('UtilService', ['$sanitize', function($sanitize) {
var utilService = {};
@ -2510,6 +2510,7 @@ quayApp.directive('ngBlur', function() {
};
});
quayApp.run(['$location', '$rootScope', 'Restangular', 'UserService', 'PlanService', '$http', '$timeout',
function($location, $rootScope, Restangular, UserService, PlanService, $http, $timeout) {

View file

@ -42,7 +42,36 @@ function PlansCtrl($scope, $location, UserService, PlanService) {
};
}
function GuideCtrl($scope) {
function GuideCtrl($scope, AngularTour, AngularTourSignals) {
$scope.startTour = function() {
AngularTour.start({
'title': 'My Test Tour',
'steps': [
{
'title': 'Welcome to the tour!',
'content': 'Some cool content'
},
{
'title': 'A step tied to a DOM element',
'content': 'This is the best DOM element!',
'element': '#test-element'
},
{
'content': 'Waiting for the page to change',
'signal': AngularTourSignals.matchesLocation('/repository/')
},
{
'content': 'Waiting for the page to load',
'signal': AngularTourSignals.elementAvaliable('*[data-repo="public/publicrepo"]')
},
{
'content': 'Now click on the public repository',
'signal': AngularTourSignals.matchesLocation('/repository/public/publicrepo'),
'element': '*[data-repo="public/publicrepo"]'
}
]
});
};
}
function SecurityCtrl($scope) {

147
static/js/tour.js Normal file
View file

@ -0,0 +1,147 @@
angular.module("angular-tour", [])
.provider('AngularTour', function() {
this.$get = ['$document', '$rootScope', '$compile', function($document, $rootScope, $compile) {
function _start(tour) {
$rootScope.angular_tour_current = tour;
}
function _stop() {
$rootScope.angular_tour_current = null;
}
return {
start: _start,
stop: _stop
};
}];
})
.directive('angularTourOverlay', function() {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/angular-tour-overlay.html',
replace: false,
transclude: false,
restrict: 'C',
scope: {
'tour': '=tour'
},
controller: function($scope, $element, $interval) {
$scope.stepIndex = 0;
$scope.step = null;
$scope.interval = null;
var checkSignalTimer = function() {
if (!$scope.step) {
stopSignalTimer();
return;
}
var signal = $scope.step.signal;
if (signal()) {
$scope.next();
}
};
var stopSignalTimer = function() {
if (!$scope.interval) { return; }
$interval.cancel($scope.interval);
$scope.interval = null;
};
var startSignalTimer = function() {
$scope.interval = $interval(checkSignalTimer, 500);
};
var closeDomHighlight = function() {
if (!$scope.step) { return; }
var element = $($scope.step.element);
element.spotlight('close');
};
var updateDomHighlight = function() {
var element = $($scope.step.element);
if (!element.length) {
return;
}
element.spotlight({
opacity: .5,
speed: 400,
color: '#333',
animate: true,
easing: 'linear',
exitEvent: 'mouseenter',
exitEventAppliesToElement: true,
paddingX: 1,
paddingY: 1
});
};
$scope.setStepIndex = function(stepIndex) {
// Close existing spotlight and signal timer.
closeDomHighlight();
stopSignalTimer();
// Check if there is a next step.
if (!$scope.tour || stepIndex >= $scope.tour.steps.length) {
$scope.step = null;
$scope.hasNextStep = false;
return;
}
$scope.step = $scope.tour.steps[stepIndex];
$scope.stepIndex = stepIndex;
$scope.hasNextStep = stepIndex < $scope.tour.steps.length - 1;
// Need the timeout here to ensure the click event does not
// hide the spotlight.
setTimeout(function() {
updateDomHighlight();
}, 1);
// Start listening for signals to move the tour forward.
if ($scope.step.signal) {
startSignalTimer();
}
};
$scope.stop = function() {
$scope.tour = null;
};
$scope.next = function() {
$scope.setStepIndex($scope.stepIndex + 1);
};
$scope.$watch('tour', function(tour) {
stopSignalTimer();
$scope.setStepIndex(0);
});
}
};
return directiveDefinitionObject;
})
.factory('AngularTourSignals', ['$location', function($location) {
var signals = {};
// Signal: When the page location matches the given path.
signals.matchesLocation = function(locationPath) {
return function() {
return $location.path() == locationPath;
};
};
// Signal: When an element is found in the page's DOM.
signals.elementAvaliable = function(elementPath) {
return function() {
return $(elementPath).length > 0;
};
};
return signals;
}]);