RED.tourGuide = (function() { var activeListeners = []; var shade; var focus; var popover; var stepContent; var targetElement; var fullscreen; var tourCache = {}; function run(tourPath, done) { done = done || function(err) { if (err) { console.error(err); } }; if (tourCache[tourPath]) { runTour(tourCache[tourPath],done); } else { /* jshint ignore:start */ // jshint<2.13 doesn't support dynamic imports. Once grunt-contrib-jshint // has been updated with the new jshint, we can stop ignoring this block import(tourPath).then(function(module) { tourCache[tourPath] = module.default; runTour(tourCache[tourPath],done); }).catch(function(err) { console.warn("Error loading tour:",err); done(err); }) /* jshint ignore:end */ } } function repositionFocus() { if (targetElement) { var pos = targetElement[0].getBoundingClientRect(); var dimension = Math.max(50, Math.max(pos.width,pos.height)*1.5); if (!fullscreen) { focus.css({ left: (pos.left+pos.width/2)+"px", top: (pos.top+pos.height/2)+"px", width: (2*dimension)+"px", height: (2*dimension)+"px" }) focus[0].offsetHeight; // Flush CSS changes focus.addClass("transition"); focus.css({ width: dimension+"px", height: dimension+"px" }) } else { focus.css({ left: ($(window).width()/2)+"px", top: ($(window).height()/2)+"px", width: "0px", height: "0px" }) } if (popover) { popover.move({ target: targetElement, }) } } } function runTour(tour, done) { shade = $('
').appendTo(document.body); focus = $('').appendTo(shade); // var resizeTimer; // $(window).on("resize.red-ui-tourGuide", function() { repositionFocus(); }) var i = 0; var state = { index: 0, count: tour.steps.length }; function endTour(err) { $(window).off("resize.red-ui-tourGuide"); if (popover) { popover.close(); } stepContent = null; popover = null; shade.remove(); shade = null; done(err); } function runStep(carryOn) { if (carryOn === false) { endTour(false); return; } if (i === tour.steps.length) { endTour(); return } state.index = i; // console.log("TOUR STEP",i+1,"OF",tour.steps.length) try { runTourStep(tour.steps[i++], state, runStep) } catch(err) { endTour(err); return; } } runStep(); } function clearListeners() { activeListeners.forEach(function(listener) { if (listener.type === "dom-event") { listener.target[0].removeEventListener(listener.event,listener.listener,listener.opts); } else if (listener.type === "nr-event") { RED.events.off(listener.event, listener.listener) } }) activeListeners = []; } function prepareStep(step, state, done) { if (step.prepare) { if (step.prepare.length === 0) { step.prepare.call(state); } else { step.prepare.call(state, done) return; } } done(); } function completeStep(step, state, done) { function finish() { clearListeners(); setTimeout(function() { done(); },0) } if (step.complete) { if (step.complete.length === 0) { step.complete.call(state); } else { step.complete.call(state, finish) return; } } finish(); } function runTourStep(step, state, done) { shade.fadeIn(); prepareStep(step, state, function() { var zIndex; var direction = step.direction || "bottom"; fullscreen = false; if (typeof step.element === "string") { targetElement = $(step.element) } else if (typeof step.element === "function") { targetElement = step.element.call(state); } else if (!step.element) { targetElement = $(".red-ui-editor") fullscreen = true; direction = "inset"; } else { targetElement = step.element; } if (targetElement.length === 0) { targetElement = null; shade.hide(); throw new Error("Element not found") } zIndex = targetElement.css("z-index"); if (!fullscreen) { targetElement.css("z-index",2002); } repositionFocus(); focus.toggleClass("disableInteraction", step.interactive === false) if (!stepContent) { stepContent = $(''); } else { stepContent.empty(); } $('').appendTo(stepContent).click(function(evt) { evt.preventDefault(); completeStep(step, state, function() { done(false); }); }) var stepDescription = $('').appendTo(stepContent); if (step.titleIcon) { $('