Я хотел бы использовать за построенным решение. Там обязательно будет тот, который соответствует вашим потребностям. Что-то простое, как jTour, или если это не покрывает его нечто более сложное, как Scriptio. Некоторые из ответов на вопрос this question также могут вас заинтересовать.
Редактировать Если вы не хотите использовать существовавшие ранее решение, я бы сделал что-то вроде этого:
var runTutorial = (function() {
// The command object holds all the different commands that can
// be used by someone for the tutorial. Each of these commands
// will recive a callback set as their `this`. This
// callback should be called by your commands when they are done
// running. The person making the tutorial won't need to know
// about the callback, the code will handle that.
var commands = {
wrap: function() {
//wrap the page in an iframe
this();
},
playsound: function (soundPath, soundLength) {
//playing a sound (duh)
setTimeout(this, soundLength);
},
highlight: function (selector) {
//animation that highlights an element.
//I'm using jQuery UI for the animation here,
// but most animation libraries should provide
// a callback for when the animation is done similarly
$(selector).effect('highlight', 'slow', this);
},
loadpage: function (pageUrl) {
//loading a new page
setTimeout(this, 500);
},
waitForClick: function() {
// when we go into the click handler `this` will no
// longer be availble to us since we will be in a
// different context, save `this` into `that` so
// we can call it later.
var that = this;
$(document).one('click', function() {
that();
});
}
},
// This function takes an array of commands
// and runs them in sequence. Each item in the
// array should be an array with the command name
// as the first item and any arguments it should be
// called with following as the rest of the items.
runTutorial = function (commandList) {
var nextCommand = function() {
if (commandList.length > 0) {
var args = commandList.shift();
// remove the command name
// from the argument list
cmd = args.shift(1);
// call the command, setting nextCommand as `this`
commands[cmd].apply(nextCommand, args);
}
}
nextCommand();
};
return runTutorial;
}());
$('#tutorialbutton').click(function() {
runTutorial([
['playsound', 'media/welcome', 1000],
['highlight', '[name=firstname]'],
['playsound', 'media/welcome2', 1500],
['waitForClick'],
['loadpage', page2],
['playsound', 'media/page2', 100]
]);
});
runTutorial
функция принимает простой массив, содержащий команды в порядке их выполняться вместе с их параметрами. Не нужно беспокоить человека, записывающего сценарий с обратными вызовами, runTutorial
обрабатывает это для них. Это имеет некоторые большие преимущества перед системой, которая требует, чтобы автор управлял обратными вызовами. Вам не нужно уникальное имя для каждой строки в скрипте, как при явных обратных вызовах, или бесконечное вложение анонимных функций. Вам не нужно переделывать что-либо, чтобы изменить порядок выполнения команд, вы просто физически переупорядочиваете их в массиве.
jsfiddle you can play with
Каждый из ваших команд нужно будет ждать, пока его действие должно быть сделано до того, как называет его обратного вызова (ака this
). Я имитирую это в скрипке, используя setTimeout
. Например, если вы используете jQuery .animate
для highlight
, он предоставляет обработчик complete
, который запускается, когда анимация завершена, просто нажмите this
(без круглых скобок вызова ()
). Если вы используете JQuery UI, он имеет встроенный 'highlight'effect, так что вы могли бы реализовать это следующим образом:
highlight: function (selector) {
//animation that highlights an element.
$(selector).effect('highlight', 'slow', this);
},
Большинство других библиотек, которые обеспечивают анимации должны предоставить аналогичную опцию обратного вызова вы можете использовать.
Управление обратным вызовом для звуков может быть сложнее в зависимости от того, как вы их играете. Если метод, который вы используете, не обеспечивает обратный вызов или способ опроса, чтобы проверить, все ли это сделано, вам просто нужно добавить еще один параметр в playsound
, который занимает длину звука в мс, а затем ждет этого задолго до продолжение:
playsound: function (soundPath, soundLength) {
//playing a sound (duh)
setTimeout(this, soundLength);
},
Обратный звонок, что первое, что пришло мне в голову. Другим решением будет http://api.jquery.com/category/deferred-object/. Не уверен, что это хорошо для кого-то, у кого нет опыта кодирования. – Johan
Альтернатива отложенному объекту jQuery: https://github.com/tildeio/rsvp.js –
Нет, обратные вызовы - это путь. Для удобства вы можете обернуть их в [Обещания] (http://api.jquery.com/category/deferred-object/). – Bergi