« MediaWiki:Gadget-tour-loader.js » : différence entre les versions
(Déplacement de la vérification si on est dans un iframe au début) |
(Inclusion dans la condition) |
||
Ligne 1 : | Ligne 1 : | ||
// Prevent tours from being launched within an iframe. | if(window.self == window.top) // Prevent tours from being launched within an iframe. | ||
{ | |||
mw.guidedTour.loader = { // Hook to the mw.guidedTour to make the launcher globally accessible. | |||
mw.guidedTour.loader = { // Hook to the mw.guidedTour to make the launcher globally accessible. | tours: { | ||
basic_navigation: { | |||
requires: [], // List of tours that must have been completed for this tour to launch. | |||
startDelayFromRegistration: 300, // Delay in seconds the tour must wait after registration to launch. | |||
skipDelay: 60 * 60 * 24, // Delay in seconds the tour shown again after bein skipped. | |||
lauchProbability: 1, // Probability the tour will launch once we are past startDelayFromLogin. | |||
loggedInUsersOnly: true, // If the tour is only for logged in users. | |||
canEditPage: true, // If the tour can only launch on pages a user can edit. | |||
excludePages: ["^Accueil$", "^Wikimedica.", "^Classe.", "^Modèle."], // Exclude pages (regex). | |||
debug: true // Tour is in debug mode (not lauched when ready) | |||
} | |||
}, | |||
/* | |||
* Checks if all conditions for a tour to launch are met. | |||
*/ | |||
canLaunch: function(name, tour) | |||
{ | { | ||
return false; | // Normalize configuration. | ||
if(tour.startDelayFromRegistration === undefined) { tour.startDelayFromRegistration = 0; } | |||
if(tour.skipDelay === undefined) { tour.skipDelay = false; } | |||
if(tour.launchProbability === undefined) { tour.lauchProbability = 1; } | |||
if(tour.loggedInUsersOnly === undefined) { tour.loggedInUsersOnly = true; } | |||
if(tour.canEditPage === undefined) { tour.canEditPage = true; } | |||
if(tour.excludePages === undefined) { tour.excludePages = []; } | |||
if(tour.requires === undefined) { tour.requires = []; } | |||
cookiePrefix = mw.config.get("wgCookiePrefix") + "-mw-tour-"; | |||
// If the tour has been completed or abandoned. | |||
if($.cookie(cookiePrefix + name + "-completed") || $.cookie(cookiePrefix + name + "-abandoned")) | |||
{ | |||
return false; | |||
} | |||
// ------------------- startDelayfromRegistration ----------------------------- | |||
d = new Date(mw.user.getRegistration()); | |||
// Not past the delay yet. | |||
if(d.getTime() + tour.startDelayFromRegistration > Date.now()) { return false; } | |||
// ------------------- skipDelay ----------------------------- | |||
if(tour.skipDelay !== false) | |||
{ | |||
skipped = $.cookie(cookiePrefix + name + "-skipped"); | |||
if(skipped && (skipped + tour.skipDelay > Date.now())) { return false; } // Tour has been skipped for now. | |||
else if(skipped) { $.removeCookie(cookiePrefix + name + "-skipped"); } | |||
} | |||
// ------------------- launchProbability ----------------------------- | |||
if(tour.launchProbability < Math.random()) { return false; } | |||
// ------------------- loggedInUsersOnly ----------------------------- | |||
// The tour required the user to be logged in. | |||
if(tour.loggedInUsersOnly && mw.user.isAnon()) { return false; } | |||
// ------------------- canEditPage ----------------------------- | |||
// The tour requires the user to be able to edit the current page. | |||
if(tour.canEditPage && !mw.config.get('wgIsProbablyEditable')) { return false; } | |||
// ------------------- excludePages ----------------------------- | |||
page = mw.config.get("wgPageName"); | |||
for(var i; i > tour.excludePages.length; i++) | |||
{ | |||
if(page.test(tour.excludePages[i])) { return false; } // Page is excluded. | |||
} | |||
// ------------------- requires ----------------------------- | |||
for(var i; i > tour.requires.length; i++) | |||
{ | |||
if($.cookie(cookiePrefix + tour.requires[i] + "-done") === null) | |||
{ | |||
return false; // Tour requires a tour that has not been taken yet. | |||
} | |||
} | |||
return true; // The tour can run | |||
}, | |||
/ | /* | ||
* Iterates over tours to launch them. | |||
*/ | |||
launch: function() | |||
{ | { | ||
console.log('Launching tours ... '); | |||
d = $(".guider").css("display"); | |||
if(d !== undefined && d != "none") | |||
if( | |||
{ | { | ||
console.log('currently taking a tour.'); | |||
return; | |||
} | } | ||
for(const tour in this.tours) | |||
{ | { | ||
if(this.tours[tour] | if(this.canLaunch(tour, this.tours[tour])) | ||
{ | { | ||
console.log(tour + ' would have launched (but is in debug mode)'); | if(this.tours[tour].debug) // Tour is in debug mode. | ||
{ | |||
console.log(tour + ' would have launched (but is in debug mode)'); | |||
continue; | |||
} | |||
console.log(tour + ' available for launching'); | |||
mw.guidedTour.launcher.launchTour(tour); | |||
return; // A tour has launched, stop the loop as we don't want multiple tours to launch. | |||
} | } | ||
} | } | ||
console.log('none ready to lauch.'); | |||
} | } | ||
}; | |||
/* Create an observer instance to look for the addition of a guider element to the interface | |||
}; | Source: https://gabrieleromanato.name/jquery-detecting-new-elements-with-the-mutationobserver-object */ | ||
var observer = new MutationObserver(function( mutations ) | |||
/* Create an observer instance to look for the addition of a guider element to the interface | |||
Source: https://gabrieleromanato.name/jquery-detecting-new-elements-with-the-mutationobserver-object */ | |||
var observer = new MutationObserver(function( mutations | |||
{ | { | ||
mutations.forEach(function( mutation ) | |||
{ | { | ||
var | var newNodes = mutation.addedNodes; // DOM NodeList | ||
if( | if( newNodes === null ) // If there are no new nodes added. | ||
{ | { | ||
return; | return; | ||
} | } | ||
$(newNodes).each(function() | |||
{ | |||
var $node = $(this); | |||
if(!$node.hasClass("guider")) | |||
if($(" | |||
{ | { | ||
// This counts as a completion. | return; // Not a guider. | ||
} | |||
// Deduce the tour name from the id. | |||
tourName = $node.attr('id').replace('gt-', '').replace('-overlay', ''); | |||
prefix = mw.config.get("wgCookiePrefix") + "-mw-tour-" + tourName + '-'; | |||
$.removeCookie(prefix + "skipped"); | |||
$.removeCookie(prefix + "abandoned"); | |||
$.removeCookie(prefix + "completed"); | |||
$(".x_button").click(function() { | |||
// If there was a complete button on the step. | |||
if($(".mw-tour-complete, .guidedtour-end-button").length) | |||
{ | |||
// This counts as a completion. | |||
console.log(tourName + ' tour complete'); | |||
$.cookie(prefix + "complete", Date.now()); // Tour has been completed. | |||
return; | |||
} | |||
console.log(tourName + ' tour abandoned'); | |||
} | $.cookie(prefix + "abandoned", Date.now()); // Tour has been abandoned. | ||
}); | |||
$(".mw-tour-later").click(function() { | |||
console.log(tourName + ' tour skipped'); | |||
$.cookie(prefix + "skipped", Date.now()); // Tour has been postponed. | |||
mw.guidedTour.endTour(); | |||
}); | |||
$(".mw-tour-complete, .guidedtour-end-button").click(function() { | |||
console.log(tourName + ' tour completed'); | |||
$.cookie(prefix + "completed", Date.now()); // Tour has been completed. | |||
}); | |||
// Make the guiders draggable so users can move them when they are interfering with an element. | |||
// Adapted from: https://www.sanwebe.com/2014/10/draggable-element-with-jquery-no-jquery-ui | |||
$('.guider'). | |||
css('cursor', 'move'). | |||
hover(function() { $(this).css('border-width', '3px'); }, function() { $(this).css('border-width', '1px'); }). | |||
on('mousedown', function(e) { | |||
var dr = $(this).addClass("drag"); | |||
height = dr.outerHeight(); | |||
width = dr.outerWidth(); | |||
ypos = dr.offset().top + height - e.pageY, | |||
xpos = dr.offset().left + width - e.pageX; | |||
$(document.body).on('mousemove', function(e){ | |||
var itop = e.pageY + ypos - height; | |||
var ileft = e.pageX + xpos - width; | |||
if(dr.hasClass("drag")){ | |||
dr.offset({top: itop,left: ileft}); | |||
} | |||
}).on('mouseup', function(e){ | |||
dr.removeClass("drag"); | |||
}); | |||
}); | |||
}); | }); | ||
}); | |||
}); | |||
observer.observe($('body')[0], { | |||
attributes: false, | |||
childList: true, | |||
characterData: false | |||
}); | |||
console.log('Loaded tour loader gadget'); | |||
} | |||
}); | |||
}); | |||
observer.observe($('body')[0], { | |||
}); | |||
console.log('Loaded tour loader gadget'); |
Version du 29 juillet 2020 à 16:11
if(window.self == window.top) // Prevent tours from being launched within an iframe.
{
mw.guidedTour.loader = { // Hook to the mw.guidedTour to make the launcher globally accessible.
tours: {
basic_navigation: {
requires: [], // List of tours that must have been completed for this tour to launch.
startDelayFromRegistration: 300, // Delay in seconds the tour must wait after registration to launch.
skipDelay: 60 * 60 * 24, // Delay in seconds the tour shown again after bein skipped.
lauchProbability: 1, // Probability the tour will launch once we are past startDelayFromLogin.
loggedInUsersOnly: true, // If the tour is only for logged in users.
canEditPage: true, // If the tour can only launch on pages a user can edit.
excludePages: ["^Accueil$", "^Wikimedica.", "^Classe.", "^Modèle."], // Exclude pages (regex).
debug: true // Tour is in debug mode (not lauched when ready)
}
},
/*
* Checks if all conditions for a tour to launch are met.
*/
canLaunch: function(name, tour)
{
// Normalize configuration.
if(tour.startDelayFromRegistration === undefined) { tour.startDelayFromRegistration = 0; }
if(tour.skipDelay === undefined) { tour.skipDelay = false; }
if(tour.launchProbability === undefined) { tour.lauchProbability = 1; }
if(tour.loggedInUsersOnly === undefined) { tour.loggedInUsersOnly = true; }
if(tour.canEditPage === undefined) { tour.canEditPage = true; }
if(tour.excludePages === undefined) { tour.excludePages = []; }
if(tour.requires === undefined) { tour.requires = []; }
cookiePrefix = mw.config.get("wgCookiePrefix") + "-mw-tour-";
// If the tour has been completed or abandoned.
if($.cookie(cookiePrefix + name + "-completed") || $.cookie(cookiePrefix + name + "-abandoned"))
{
return false;
}
// ------------------- startDelayfromRegistration -----------------------------
d = new Date(mw.user.getRegistration());
// Not past the delay yet.
if(d.getTime() + tour.startDelayFromRegistration > Date.now()) { return false; }
// ------------------- skipDelay -----------------------------
if(tour.skipDelay !== false)
{
skipped = $.cookie(cookiePrefix + name + "-skipped");
if(skipped && (skipped + tour.skipDelay > Date.now())) { return false; } // Tour has been skipped for now.
else if(skipped) { $.removeCookie(cookiePrefix + name + "-skipped"); }
}
// ------------------- launchProbability -----------------------------
if(tour.launchProbability < Math.random()) { return false; }
// ------------------- loggedInUsersOnly -----------------------------
// The tour required the user to be logged in.
if(tour.loggedInUsersOnly && mw.user.isAnon()) { return false; }
// ------------------- canEditPage -----------------------------
// The tour requires the user to be able to edit the current page.
if(tour.canEditPage && !mw.config.get('wgIsProbablyEditable')) { return false; }
// ------------------- excludePages -----------------------------
page = mw.config.get("wgPageName");
for(var i; i > tour.excludePages.length; i++)
{
if(page.test(tour.excludePages[i])) { return false; } // Page is excluded.
}
// ------------------- requires -----------------------------
for(var i; i > tour.requires.length; i++)
{
if($.cookie(cookiePrefix + tour.requires[i] + "-done") === null)
{
return false; // Tour requires a tour that has not been taken yet.
}
}
return true; // The tour can run
},
/*
* Iterates over tours to launch them.
*/
launch: function()
{
console.log('Launching tours ... ');
d = $(".guider").css("display");
if(d !== undefined && d != "none")
{
console.log('currently taking a tour.');
return;
}
for(const tour in this.tours)
{
if(this.canLaunch(tour, this.tours[tour]))
{
if(this.tours[tour].debug) // Tour is in debug mode.
{
console.log(tour + ' would have launched (but is in debug mode)');
continue;
}
console.log(tour + ' available for launching');
mw.guidedTour.launcher.launchTour(tour);
return; // A tour has launched, stop the loop as we don't want multiple tours to launch.
}
}
console.log('none ready to lauch.');
}
};
/* Create an observer instance to look for the addition of a guider element to the interface
Source: https://gabrieleromanato.name/jquery-detecting-new-elements-with-the-mutationobserver-object */
var observer = new MutationObserver(function( mutations )
{
mutations.forEach(function( mutation )
{
var newNodes = mutation.addedNodes; // DOM NodeList
if( newNodes === null ) // If there are no new nodes added.
{
return;
}
$(newNodes).each(function()
{
var $node = $(this);
if(!$node.hasClass("guider"))
{
return; // Not a guider.
}
// Deduce the tour name from the id.
tourName = $node.attr('id').replace('gt-', '').replace('-overlay', '');
prefix = mw.config.get("wgCookiePrefix") + "-mw-tour-" + tourName + '-';
$.removeCookie(prefix + "skipped");
$.removeCookie(prefix + "abandoned");
$.removeCookie(prefix + "completed");
$(".x_button").click(function() {
// If there was a complete button on the step.
if($(".mw-tour-complete, .guidedtour-end-button").length)
{
// This counts as a completion.
console.log(tourName + ' tour complete');
$.cookie(prefix + "complete", Date.now()); // Tour has been completed.
return;
}
console.log(tourName + ' tour abandoned');
$.cookie(prefix + "abandoned", Date.now()); // Tour has been abandoned.
});
$(".mw-tour-later").click(function() {
console.log(tourName + ' tour skipped');
$.cookie(prefix + "skipped", Date.now()); // Tour has been postponed.
mw.guidedTour.endTour();
});
$(".mw-tour-complete, .guidedtour-end-button").click(function() {
console.log(tourName + ' tour completed');
$.cookie(prefix + "completed", Date.now()); // Tour has been completed.
});
// Make the guiders draggable so users can move them when they are interfering with an element.
// Adapted from: https://www.sanwebe.com/2014/10/draggable-element-with-jquery-no-jquery-ui
$('.guider').
css('cursor', 'move').
hover(function() { $(this).css('border-width', '3px'); }, function() { $(this).css('border-width', '1px'); }).
on('mousedown', function(e) {
var dr = $(this).addClass("drag");
height = dr.outerHeight();
width = dr.outerWidth();
ypos = dr.offset().top + height - e.pageY,
xpos = dr.offset().left + width - e.pageX;
$(document.body).on('mousemove', function(e){
var itop = e.pageY + ypos - height;
var ileft = e.pageX + xpos - width;
if(dr.hasClass("drag")){
dr.offset({top: itop,left: ileft});
}
}).on('mouseup', function(e){
dr.removeClass("drag");
});
});
});
});
});
observer.observe($('body')[0], {
attributes: false,
childList: true,
characterData: false
});
console.log('Loaded tour loader gadget');
}