1 | /*
|
2 | * Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
|
3 | *
|
4 | * Permission is hereby granted, free of charge, to any person obtaining a
|
5 | * copy of this software and associated documentation files (the "Software"),
|
6 | * to deal in the Software without restriction, including without limitation
|
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
8 | * and/or sell copies of the Software, and to permit persons to whom the
|
9 | * Software is furnished to do so, subject to the following conditions:
|
10 | *
|
11 | * The above copyright notice and this permission notice shall be included in
|
12 | * all copies or substantial portions of the Software.
|
13 | *
|
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
20 | * DEALINGS IN THE SOFTWARE.
|
21 | *
|
22 | */
|
23 |
|
24 |
|
25 | /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
|
26 | /*global require, define, brackets: true, $, PathUtils, window, navigator, Mustache */
|
27 |
|
28 | require.config({
|
29 | paths: {
|
30 | "text" : "thirdparty/text",
|
31 | "i18n" : "thirdparty/i18n"
|
32 | },
|
33 | // Use custom brackets property until CEF sets the correct navigator.language
|
34 | // NOTE: When we change to navigator.language here, we also should change to
|
35 | // navigator.language in ExtensionLoader (when making require contexts for each
|
36 | // extension).
|
37 | locale: window.localStorage.getItem("locale") || (typeof (brackets) !== "undefined" ? brackets.app.language : navigator.language)
|
38 | });
|
39 |
|
40 | /**
|
41 | * brackets is the root of the Brackets codebase. This file pulls in all other modules as
|
42 | * dependencies (or dependencies thereof), initializes the UI, and binds global menus & keyboard
|
43 | * shortcuts to their Commands.
|
44 | *
|
45 | * TODO: (issue #264) break out the definition of brackets into a separate module from the application controller logic
|
46 | *
|
47 | * Unlike other modules, this one can be accessed without an explicit require() because it exposes
|
48 | * a global object, window.brackets.
|
49 | */
|
50 | define(function (require, exports, module) {
|
51 | ;
|
52 |
|
53 | // Load dependent non-module scripts
|
54 | require("widgets/bootstrap-dropdown");
|
55 | require("widgets/bootstrap-modal");
|
56 | require("thirdparty/path-utils/path-utils.min");
|
57 | require("thirdparty/smart-auto-complete/jquery.smart_autocomplete");
|
58 |
|
59 | // Load LiveDeveopment
|
60 | require("LiveDevelopment/main");
|
61 |
|
62 | // Load dependent modules
|
63 | var Global = require("utils/Global"),
|
64 | AppInit = require("utils/AppInit"),
|
65 | ProjectManager = require("project/ProjectManager"),
|
66 | DocumentManager = require("document/DocumentManager"),
|
67 | EditorManager = require("editor/EditorManager"),
|
68 | CSSInlineEditor = require("editor/CSSInlineEditor"),
|
69 | JSUtils = require("language/JSUtils"),
|
70 | WorkingSetView = require("project/WorkingSetView"),
|
71 | WorkingSetSort = require("project/WorkingSetSort"),
|
72 | DocumentCommandHandlers = require("document/DocumentCommandHandlers"),
|
73 | FileViewController = require("project/FileViewController"),
|
74 | FileSyncManager = require("project/FileSyncManager"),
|
75 | KeyBindingManager = require("command/KeyBindingManager"),
|
76 | Commands = require("command/Commands"),
|
77 | CommandManager = require("command/CommandManager"),
|
78 | CodeHintManager = require("editor/CodeHintManager"),
|
79 | JSLintUtils = require("language/JSLintUtils"),
|
80 | PerfUtils = require("utils/PerfUtils"),
|
81 | FileIndexManager = require("project/FileIndexManager"),
|
82 | QuickOpen = require("search/QuickOpen"),
|
83 | Menus = require("command/Menus"),
|
84 | FileUtils = require("file/FileUtils"),
|
85 | MainViewHTML = require("text!htmlContent/main-view.html"),
|
86 | Strings = require("strings"),
|
87 | Dialogs = require("widgets/Dialogs"),
|
88 | ExtensionLoader = require("utils/ExtensionLoader"),
|
89 | SidebarView = require("project/SidebarView"),
|
90 | Async = require("utils/Async"),
|
91 | UpdateNotification = require("utils/UpdateNotification"),
|
92 | UrlParams = require("utils/UrlParams").UrlParams,
|
93 | NativeFileSystem = require("file/NativeFileSystem").NativeFileSystem,
|
94 | PreferencesManager = require("preferences/PreferencesManager"),
|
95 | Resizer = require("utils/Resizer");
|
96 |
|
97 | // Local variables
|
98 | var params = new UrlParams(),
|
99 | PREFERENCES_CLIENT_ID = "com.adobe.brackets.startup";
|
100 |
|
101 | // read URL params
|
102 | params.parse();
|
103 |
|
104 | //Load modules that self-register and just need to get included in the main project
|
105 | require("document/ChangedDocumentTracker");
|
106 | require("editor/EditorCommandHandlers");
|
107 | require("view/ViewCommandHandlers");
|
108 | require("debug/DebugCommandHandlers");
|
109 | require("help/HelpCommandHandlers");
|
110 | require("search/FindInFiles");
|
111 | require("search/FindReplace");
|
112 | require("utils/ExtensionUtils");
|
113 |
|
114 | function _initExtensions() {
|
115 | // allow unit tests to override which plugin folder(s) to load
|
116 | var paths = params.get("extensions");
|
117 |
|
118 | if (!paths) {
|
119 | paths = "default,dev," + ExtensionLoader.getUserExtensionPath();
|
120 | }
|
121 |
|
122 | return Async.doInParallel(paths.split(","), function (item) {
|
123 | var extensionPath = item;
|
124 |
|
125 | // If the item has "/" in it, assume it is a full path. Otherwise, load
|
126 | // from our source path + "/extensions/".
|
127 | if (item.indexOf("/") === -1) {
|
128 | extensionPath = FileUtils.getNativeBracketsDirectoryPath() + "/extensions/" + item;
|
129 | }
|
130 |
|
131 | return ExtensionLoader.loadAllExtensionsInNativeDirectory(extensionPath);
|
132 | });
|
133 | }
|
134 |
|
135 | function _initTest() {
|
136 | // TODO: (issue #265) Make sure the "test" object is not included in final builds
|
137 | // All modules that need to be tested from the context of the application
|
138 | // must to be added to this object. The unit tests cannot just pull
|
139 | // in the modules since they would run in context of the unit test window,
|
140 | // and would not have access to the app html/css.
|
141 | brackets.test = {
|
142 | PreferencesManager : require("preferences/PreferencesManager"),
|
143 | ProjectManager : ProjectManager,
|
144 | DocumentCommandHandlers : DocumentCommandHandlers,
|
145 | FileViewController : FileViewController,
|
146 | DocumentManager : DocumentManager,
|
147 | EditorManager : EditorManager,
|
148 | Commands : Commands,
|
149 | WorkingSetView : WorkingSetView,
|
150 | JSLintUtils : JSLintUtils,
|
151 | PerfUtils : PerfUtils,
|
152 | JSUtils : JSUtils,
|
153 | CommandManager : require("command/CommandManager"),
|
154 | FileSyncManager : FileSyncManager,
|
155 | FileIndexManager : FileIndexManager,
|
156 | Menus : Menus,
|
157 | KeyBindingManager : KeyBindingManager,
|
158 | CodeHintManager : CodeHintManager,
|
159 | CSSUtils : require("language/CSSUtils"),
|
160 | LiveDevelopment : require("LiveDevelopment/LiveDevelopment"),
|
161 | DOMAgent : require("LiveDevelopment/Agents/DOMAgent"),
|
162 | Inspector : require("LiveDevelopment/Inspector/Inspector"),
|
163 | NativeApp : require("utils/NativeApp"),
|
164 | ExtensionUtils : require("utils/ExtensionUtils"),
|
165 | UpdateNotification : require("utils/UpdateNotification"),
|
166 | doneLoading : false
|
167 | };
|
168 |
|
169 | AppInit.appReady(function () {
|
170 | brackets.test.doneLoading = true;
|
171 | });
|
172 | }
|
173 |
|
174 | function _initDragAndDropListeners() {
|
175 | // Prevent unhandled drag and drop of files into the browser from replacing
|
176 | // the entire Brackets app. This doesn't prevent children from choosing to
|
177 | // handle drops.
|
178 | $(window.document.body)
|
179 | .on("dragover", function (event) {
|
180 | if (event.originalEvent.dataTransfer.files) {
|
181 | event.stopPropagation();
|
182 | event.preventDefault();
|
183 | event.originalEvent.dataTransfer.dropEffect = "none";
|
184 | }
|
185 | })
|
186 | .on("drop", function (event) {
|
187 | if (event.originalEvent.dataTransfer.files) {
|
188 | event.stopPropagation();
|
189 | event.preventDefault();
|
190 | }
|
191 | });
|
192 | }
|
193 |
|
194 | function _initCommandHandlers() {
|
195 | // Most command handlers are automatically registered when their module is loaded (see "modules
|
196 | // that self-register" above for some). A few commands need an extra kick here though:
|
197 |
|
198 | DocumentCommandHandlers.init($("#main-toolbar"));
|
199 | }
|
200 |
|
201 | function _initWindowListeners() {
|
202 | // TODO: (issue 269) to support IE, need to listen to document instead (and even then it may not work when focus is in an input field?)
|
203 | $(window).focus(function () {
|
204 | FileSyncManager.syncOpenDocuments();
|
205 | FileIndexManager.markDirty();
|
206 | });
|
207 |
|
208 | }
|
209 |
|
210 | function _onReady() {
|
211 | // Add the platform (mac or win) to the body tag so we can have platform-specific CSS rules
|
212 | $("body").addClass("platform-" + brackets.platform);
|
213 |
|
214 | EditorManager.setEditorHolder($("#editor-holder"));
|
215 |
|
216 | _initDragAndDropListeners();
|
217 | _initCommandHandlers();
|
218 | KeyBindingManager.init();
|
219 | Menus.init(); // key bindings should be initialized first
|
220 | _initWindowListeners();
|
221 |
|
222 | // Use quiet scrollbars if we aren't on Lion. If we're on Lion, only
|
223 | // use native scroll bars when the mouse is not plugged in or when
|
224 | // using the "Always" scroll bar setting.
|
225 | var osxMatch = /Mac OS X 10\D([\d+])\D/.exec(navigator.userAgent);
|
226 | if (osxMatch && osxMatch[1] && Number(osxMatch[1]) >= 7) {
|
227 | // test a scrolling div for scrollbars
|
228 | var $testDiv = $("<div style='position:fixed;left:-50px;width:50px;height:50px;overflow:auto;'><div style='width:100px;height:100px;'/></div>").appendTo(window.document.body);
|
229 |
|
230 | if ($testDiv.outerWidth() === $testDiv.get(0).clientWidth) {
|
231 | $(".sidebar").removeClass("quiet-scrollbars");
|
232 | }
|
233 |
|
234 | $testDiv.remove();
|
235 | }
|
236 |
|
237 | PerfUtils.addMeasurement("Application Startup");
|
238 |
|
239 | // finish UI initialization before loading extensions
|
240 | var initialProjectPath = ProjectManager.getInitialProjectPath();
|
241 | ProjectManager.openProject(initialProjectPath).always(function () {
|
242 | _initTest();
|
243 |
|
244 | // Create a new DirectoryEntry and call getDirectory() on the user extension
|
245 | // directory. If the directory doesn't exist, it will be created.
|
246 | // Note that this is an async call and there are no success or failure functions passed
|
247 | // in. If the directory *doesn't* exist, it will be created. Extension loading may happen
|
248 | // before the directory is finished being created, but that is okay, since the extension
|
249 | // loading will work correctly without this directory.
|
250 | // If the directory *does* exist, nothing else needs to be done. It will be scanned normally
|
251 | // during extension loading.
|
252 | var extensionPath = ExtensionLoader.getUserExtensionPath();
|
253 | new NativeFileSystem.DirectoryEntry().getDirectory(extensionPath,
|
254 | {create: true});
|
255 |
|
256 | // Create the extensions/disabled directory, too.
|
257 | var disabledExtensionPath = extensionPath.replace(/\/user$/, "/disabled");
|
258 | new NativeFileSystem.DirectoryEntry().getDirectory(disabledExtensionPath,
|
259 | {create: true});
|
260 |
|
261 | // Load all extensions, and when done fire APP_READY (even if some extensions failed
|
262 | // to load or initialize)
|
263 | _initExtensions().always(function () {
|
264 | AppInit._dispatchReady(AppInit.APP_READY);
|
265 | });
|
266 |
|
267 | // If this is the first launch, and we have an index.html file in the project folder (which should be
|
268 | // the samples folder on first launch), open it automatically. (We explicitly check for the
|
269 | // samples folder in case this is the first time we're launching Brackets after upgrading from
|
270 | // an old version that might not have set the "afterFirstLaunch" pref.)
|
271 | var prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID);
|
272 | if (!params.get("skipSampleProjectLoad") && !prefs.getValue("afterFirstLaunch")) {
|
273 | prefs.setValue("afterFirstLaunch", "true");
|
274 | if (ProjectManager.isWelcomeProjectPath(initialProjectPath)) {
|
275 | var dirEntry = new NativeFileSystem.DirectoryEntry(initialProjectPath);
|
276 | dirEntry.getFile("index.html", {}, function (fileEntry) {
|
277 | CommandManager.execute(Commands.FILE_ADD_TO_WORKING_SET, { fullPath: fileEntry.fullPath });
|
278 | });
|
279 | }
|
280 | }
|
281 | });
|
282 |
|
283 | // Check for updates
|
284 | if (!params.get("skipUpdateCheck") && !brackets.inBrowser) {
|
285 | UpdateNotification.checkForUpdate();
|
286 | }
|
287 | }
|
288 |
|
289 | // Prevent unhandled middle button clicks from triggering native behavior
|
290 | // Example: activating AutoScroll (see #510)
|
291 | $("html").on("mousedown", ".inline-widget", function (e) {
|
292 | if (e.button === 1) {
|
293 | e.preventDefault();
|
294 | }
|
295 | });
|
296 |
|
297 | // Localize MainViewHTML and inject into <BODY> tag
|
298 | var templateVars = $.extend({
|
299 | ABOUT_ICON : brackets.config.about_icon,
|
300 | APP_NAME_ABOUT_BOX : brackets.config.app_name_about,
|
301 | VERSION : brackets.metadata.version
|
302 | }, Strings);
|
303 |
|
304 | $("body").html(Mustache.render(MainViewHTML, templateVars));
|
305 |
|
306 | // Update title
|
307 | $("title").text(brackets.config.app_title);
|
308 |
|
309 | // Dispatch htmlReady callbacks
|
310 | AppInit._dispatchReady(AppInit.HTML_READY);
|
311 |
|
312 | $(window.document).ready(_onReady);
|
313 |
|
314 | });
|