1 /**
  2  * <pre>
  3  * Listens to HELP_COMMAND and displays notifications.
  4  * Provides interactive tutorial for first time users.
  5  * </pre>
  6  * 
  7  * @constructor
  8  * @param {mindmaps.EventBus} eventBus
  9  * @param {mindmaps.commandRegistry} commandRegistry
 10  */
 11 mindmaps.HelpController = function(eventBus, commandRegistry) {
 12 
 13 	/**
 14 	 * Prepare tutorial guiders.
 15 	 */
 16 	function setupInteractiveMode() {
 17 		if (isTutorialDone()) {
 18 			console.debug("skipping tutorial");
 19 			return;
 20 		}
 21 
 22 		var notifications = [];
 23 		var interactiveMode = true;
 24 
 25 		// start tutorial after a short delay
 26 		eventBus.once(mindmaps.Event.DOCUMENT_OPENED, function() {
 27 			setTimeout(start, 1000);
 28 		});
 29 
 30 		function closeAllNotifications() {
 31 			notifications.forEach(function(n) {
 32 				n.close();
 33 			});
 34 		}
 35 
 36 		var helpMain, helpRoot;
 37 		function start() {
 38 			helpMain = new mindmaps.Notification(
 39 					"#toolbar",
 40 					{
 41 						position : "bottomMiddle",
 42 						maxWidth : 550,
 43 						title : "Welcome to mindmaps",
 44 						content : "Hello there, it seems like you are new here! These bubbles "
 45 								+ "will guide you through the app. Or they won't if you want to skip this tutorial and <a class='skip-tutorial link'>click here<a/>."
 46 					});
 47 			notifications.push(helpMain);
 48 			helpMain.$().find("a.skip-tutorial").click(function() {
 49 				interactiveMode = false;
 50 				closeAllNotifications();
 51 				tutorialDone();
 52 			});
 53 			setTimeout(theRoot, 2000);
 54 		}
 55 
 56 		function theRoot() {
 57 			if (isTutorialDone())
 58 				return;
 59 
 60 			helpRoot = new mindmaps.Notification(
 61 					".node-caption.root",
 62 					{
 63 						position : "bottomMiddle",
 64 						closeButton : true,
 65 						maxWidth : 350,
 66 						title : "This is where you start - your main idea",
 67 						content : "Double click the idea to change what it says. This will be the main topic of your mind map."
 68 					});
 69 			notifications.push(helpRoot);
 70 
 71 			eventBus.once(mindmaps.Event.NODE_TEXT_CAPTION_CHANGED, function() {
 72 				helpRoot.close();
 73 				setTimeout(theNub, 900);
 74 			});
 75 		}
 76 
 77 		function theNub() {
 78 			if (isTutorialDone())
 79 				return;
 80 
 81 			var helpNub = new mindmaps.Notification(
 82 					".node-caption.root",
 83 					{
 84 						position : "bottomMiddle",
 85 						closeButton : true,
 86 						maxWidth : 350,
 87 						padding : 20,
 88 						title : "Creating new ideas",
 89 						content : "Now it's time to build your mind map.<br/> Move your mouse over the idea, click and then drag"
 90 								+ " the <span style='color:red'>red circle</span> away from the root. This is how you create a new branch."
 91 					});
 92 			notifications.push(helpNub);
 93 			eventBus.once(mindmaps.Event.NODE_CREATED, function() {
 94 				helpMain.close();
 95 				helpNub.close();
 96 				setTimeout(newNode, 900);
 97 			});
 98 		}
 99 
100 		function newNode() {
101 			if (isTutorialDone())
102 				return;
103 
104 			var helpNewNode = new mindmaps.Notification(
105 					".node-container.root > .node-container:first",
106 					{
107 						position : "bottomMiddle",
108 						closeButton : true,
109 						maxWidth : 350,
110 						title : "Your first branch",
111 						content : "Great! This is easy, right? The red circle is your most important tool. Now, you can move your idea"
112 								+ " around by dragging it or double click to change the text again."
113 					});
114 			notifications.push(helpNewNode);
115 			setTimeout(inspector, 2000);
116 
117 			eventBus.once(mindmaps.Event.NODE_MOVED, function() {
118 				helpNewNode.close();
119 				setTimeout(navigate, 0);
120 				setTimeout(toolbar, 15000);
121 				setTimeout(menu, 10000);
122 				setTimeout(tutorialDone, 20000);
123 			});
124 		}
125 
126 		function navigate() {
127 			if (isTutorialDone())
128 				return;
129 
130 			var helpNavigate = new mindmaps.Notification(
131 					".float-panel:has(#navigator)",
132 					{
133 						position : "bottomRight",
134 						closeButton : true,
135 						maxWidth : 350,
136 						expires : 10000,
137 						title : "Navigation",
138 						content : "You can click and drag the background of the map to move around. Use your mousewheel or slider over there to zoom in and out."
139 					});
140 			notifications.push(helpNavigate);
141 		}
142 
143 		function inspector() {
144 			if (isTutorialDone())
145 				return;
146 
147 			var helpInspector = new mindmaps.Notification(
148 					"#inspector",
149 					{
150 						position : "leftBottom",
151 						closeButton : true,
152 						maxWidth : 350,
153 						padding : 20,
154 						title : "Don't like the colors?",
155 						content : "Use these controls to change the appearance of your ideas. "
156 								+ "Try clicking the icon in the upper right corner to minimize this panel."
157 					});
158 			notifications.push(helpInspector);
159 		}
160 
161 		function toolbar() {
162 			if (isTutorialDone())
163 				return;
164 
165 			var helpToolbar = new mindmaps.Notification(
166 					"#toolbar .buttons-left",
167 					{
168 						position : "bottomLeft",
169 						closeButton : true,
170 						maxWidth : 350,
171 						padding : 20,
172 						title : "The tool bar",
173 						content : "Those buttons do what they say. You can use them or work with keyboard shortcuts. "
174 								+ "Hover over the buttons for the key combinations."
175 					});
176 			notifications.push(helpToolbar);
177 		}
178 
179 		function menu() {
180 			if (isTutorialDone())
181 				return;
182 
183 			var helpMenu = new mindmaps.Notification(
184 					"#toolbar .buttons-right",
185 					{
186 						position : "leftTop",
187 						closeButton : true,
188 						maxWidth : 350,
189 						title : "Save your work",
190 						content : "The button to the right opens a menu where you can save your mind map or start working "
191 								+ "on another one if you like."
192 					});
193 			notifications.push(helpMenu);
194 		}
195 
196 		function isTutorialDone() {
197 			return mindmaps.LocalStorage.get("mindmaps.tutorial.done") == 1;
198 		}
199 
200 		function tutorialDone() {
201 			mindmaps.LocalStorage.put("mindmaps.tutorial.done", 1);
202 		}
203 
204 	}
205 
206 	/**
207 	 * Prepares notfications to show for help command.
208 	 */
209 	function setupHelpButton() {
210 		var command = commandRegistry.get(mindmaps.HelpCommand);
211 		command.setHandler(showHelp);
212 
213 		var notifications = [];
214 		function showHelp() {
215 			// true if atleast one notifications is still on screen
216 			var displaying = notifications.some(function(noti) {
217 				return noti.isVisible();
218 			});
219 
220 			// hide notifications if visible
221 			if (displaying) {
222 				notifications.forEach(function(noti) {
223 					noti.close();
224 				});
225 				notifications.length = 0;
226 				return;
227 			}
228 
229 			// show notifications
230 			var helpRoot = new mindmaps.Notification(
231 					".node-caption.root",
232 					{
233 						position : "bottomLeft",
234 						closeButton : true,
235 						maxWidth : 350,
236 						title : "This is your main idea",
237 						content : "Double click an idea to edit its text. Move the mouse over "
238 								+ "an idea and drag the red circle to create a new idea."
239 					});
240 
241 			var helpNavigator = new mindmaps.Notification(
242 					"#navigator",
243 					{
244 						position : "leftTop",
245 						closeButton : true,
246 						maxWidth : 350,
247 						padding : 20,
248 						title : "This is the navigator",
249 						content : "Use this panel to get an overview of your map. "
250 								+ "You can navigate around by dragging the red rectangle or change the zoom by clicking on the magnifier buttons."
251 					});
252 
253 			var helpInspector = new mindmaps.Notification(
254 					"#inspector",
255 					{
256 						position : "leftTop",
257 						closeButton : true,
258 						maxWidth : 350,
259 						padding : 20,
260 						title : "This is the inspector",
261 						content : "Use these controls to change the appearance of your ideas. "
262 								+ "Try clicking the icon in the upper right corner to minimize this panel."
263 					});
264 
265 			var helpToolbar = new mindmaps.Notification(
266 					"#toolbar .buttons-left",
267 					{
268 						position : "bottomLeft",
269 						closeButton : true,
270 						maxWidth : 350,
271 						title : "This is your toolbar",
272 						content : "Those buttons do what they say. You can use them or work with keyboard shortcuts. "
273 								+ "Hover over the buttons for the key combinations."
274 					});
275 
276 			notifications.push(helpRoot, helpNavigator, helpInspector,
277 					helpToolbar);
278 		}
279 	}
280 
281 	setupInteractiveMode();
282 	setupHelpButton();
283 };
284