define(function(require, exports, module) { main.consumes = [ "Plugin", "ui", "commands", "menus", "settings", "info", "c9.analytics", "c9" ]; main.provides = ["guide"]; return main; function main(options, imports, register) { var Plugin = imports.Plugin; var ui = imports.ui; var menus = imports.menus; var commands = imports.commands; var settings = imports.settings; var c9 = imports.c9; var info = imports.info; var analytics = imports["c9.analytics"]; /***** Initialization *****/ var plugin = new Plugin("Ajax.org", main.consumes); var emit = plugin.getEmitter(); var RIGHT = 1 << 1; var LEFT = 1 << 2; var BOTTOM = 1 << 3; var TOP = 1 << 4; var THINGY_MARGIN = 0; var THINGY_SIZE = 10; var POPUP_MARGIN = 17; var thingies, popup, showing, currentPopup; var timer, listen; function load() { menus.addItemByPath("Support/Show Guided Tour", new ui.item({ onclick: show, }), 150, plugin); } var drawn = false; function draw() { if (drawn) return; drawn = true; // Insert CSS ui.insertCss(require("text!./style.css"), options.staticPrefix, plugin); // Draw the thingies thingies.forEach(drawThingy); emit("draw"); } /***** Methods *****/ function add(t) { if (!(t instanceof Array)) t = [t]; if (!thingies) thingies = t; else { t.forEach(function(i) { thingies.push(i); if (!drawn) drawThingy(i); }); } } function setPosition(htmlNode, pos, def, width, height, margin, isThingy, isUpdate) { htmlNode.style.right = htmlNode.style.left = htmlNode.style.top = htmlNode.style.bottom = ""; function right() { return window.innerWidth - pos.left - pos.width; } function bottom() { return window.innerHeight - pos.top - pos.height; } var offsetW = isThingy ? width / 2 : 0; var offsetH = isThingy ? height / 2 : 0; var corW = isThingy ? 0 : width; var corH = isThingy ? 0 : height; var maxW = window.innerWidth - corW - margin; var maxH = window.innerHeight - corH - margin; var where = isThingy ? def.where : def.wherePopup || def.where; if (where & LEFT) { if (def.attachment & RIGHT) htmlNode.style.right = (right() + pos.width - offsetW + margin) + "px"; else htmlNode.style.left = (pos.left - corW - offsetW - margin) + "px"; } else if (where & RIGHT) { if (def.attachment & RIGHT) htmlNode.style.right = (right() + pos.width + margin - offsetW) + "px"; else htmlNode.style.left = (pos.left + pos.width + margin - offsetW) + "px"; } else { if (def.attachment & RIGHT) htmlNode.style.right = Math.max(margin, (right() + ((pos.width - width) / 2))) + "px"; else htmlNode.style.left = Math.min(maxW, Math.max(margin, (pos.left + ((pos.width - width) / 2)))) + "px"; } if (where & TOP) { if (def.attachment & BOTTOM) htmlNode.style.bottom = (bottom() + pos.height - offsetH + margin) + "px"; else htmlNode.style.top = (pos.top - corH - offsetH - margin) + "px"; } else if (where & BOTTOM) { if (def.attachment & BOTTOM) htmlNode.style.bottom = (bottom() + pos.height + margin - offsetH) + "px"; else htmlNode.style.top = (pos.top + pos.height + margin - offsetH) + "px"; } else { if (def.attachment & BOTTOM) htmlNode.style.bottom = Math.max(margin, (bottom() + ((pos.height - height) / 2))) + "px"; else htmlNode.style.top = Math.min(maxH, Math.max(margin, (pos.top + ((pos.height - height) / 2)))) + "px"; } if (!isThingy) updateBalloon(htmlNode, def); } function updateBalloon(htmlNode, def) { var h; htmlNode.classList.remove("balloon-right", "balloon-left", "balloon-top", "balloon-bottom"); var where = def.wherePopup || def.where; if (where & LEFT) htmlNode.classList.add("balloon-right"), h = 0; else if (where & RIGHT) htmlNode.classList.add("balloon-left"), h = 0; if (where & BOTTOM) htmlNode.classList.add("balloon-top"), h = 1; else if (where & TOP) htmlNode.classList.add("balloon-bottom"), h = 1; var balloon = popup.firstElementChild; balloon.style.left = balloon.style.top = ""; if (!(where & BOTTOM)) balloon.classList.add("white"); else balloon.classList.remove("white"); if (htmlNode.className.match(/balloon/g).length == 2) return; if (h == 0) { balloon.style.top = (def.thingy.offsetTop - htmlNode.offsetTop - THINGY_SIZE - 1) + "px"; } else { balloon.style.left = (def.thingy.offsetLeft - htmlNode.offsetLeft - THINGY_SIZE - 1) + "px"; } } function drawThingy(def) { var el = typeof def.query === "function" ? def.query() : document.querySelector(def.query); if (!el) return; var thingy = document.body.appendChild(document.createElement("div")); thingy.className = "thingy"; var pos = el.getBoundingClientRect(); setPosition(thingy, pos, def, THINGY_SIZE, THINGY_SIZE, THINGY_MARGIN, true); thingy.onclick = function() { togglePopup(def); }; def.body = def.body.replace(/\$\{key:([a-zA-Z]+)\}/g, function(match, name) { return commands.getPrettyHotkey(name); }); def.el = el; def.thingy = thingy; } function togglePopup(def) { if (popup && currentPopup === def) { hidePopup(true); return; } showPopup(def); } function showPopup(def) { analytics.track("Showed Guide Popup", { title: def.name }); if (!popup) { popup = document.body.appendChild(document.createElement("div")); popup.className = "thingy-popup"; // popup.title = def.title; popup.innerHTML = "
" + "" + "" + "" + "