Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1425 from adobe/jason-sanjose/issue-1404
Browse files Browse the repository at this point in the history
Refactor global brackets ready and htmlContentLoadComplete events to a new Global module
  • Loading branch information
joelrbrandt committed Aug 24, 2012
2 parents 79f9c57 + 629b7d5 commit 20a56cb
Show file tree
Hide file tree
Showing 17 changed files with 252 additions and 141 deletions.
2 changes: 2 additions & 0 deletions src/LiveDevelopment/Agents/GotoAgent.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
define(function GotoAgent(require, exports, module) {
"use strict";

require("utils/Global");

var Inspector = require("LiveDevelopment/Inspector/Inspector");
var DOMAgent = require("LiveDevelopment/Agents/DOMAgent");
var ScriptAgent = require("LiveDevelopment/Agents/ScriptAgent");
Expand Down
2 changes: 2 additions & 0 deletions src/LiveDevelopment/LiveDevelopment.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
define(function LiveDevelopment(require, exports, module) {
"use strict";

require("utils/Global");

// Status Codes
var STATUS_ERROR = exports.STATUS_ERROR = -1;
var STATUS_INACTIVE = exports.STATUS_INACTIVE = 0;
Expand Down
109 changes: 12 additions & 97 deletions src/brackets.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ require.config({
*
* Unlike other modules, this one can be accessed without an explicit require() because it exposes
* a global object, window.brackets.
*
* Events:
* htmlContentLoadComplete - sent when the HTML DOM is fully loaded. Modules should not touch
* or modify DOM elements before this event is sent.
*/
define(function (require, exports, module) {
"use strict";
Expand All @@ -64,7 +60,9 @@ define(function (require, exports, module) {
require("LiveDevelopment/main");

// Load dependent modules
var ProjectManager = require("project/ProjectManager"),
var Global = require("utils/Global"),
LoadEvents = require("utils/LoadEvents"),
ProjectManager = require("project/ProjectManager"),
DocumentManager = require("document/DocumentManager"),
EditorManager = require("editor/EditorManager"),
CSSInlineEditor = require("editor/CSSInlineEditor"),
Expand Down Expand Up @@ -94,9 +92,7 @@ define(function (require, exports, module) {
UrlParams = require("utils/UrlParams").UrlParams;

// Local variables
var bracketsReady = false,
bracketsReadyHandlers = [],
params = new UrlParams();
var params = new UrlParams();

// read URL params
params.parse();
Expand All @@ -109,89 +105,9 @@ define(function (require, exports, module) {
require("search/FindInFiles");
require("search/FindReplace");
require("utils/ExtensionUtils");

function _callBracketsReadyHandler(handler) {
try {
handler();
} catch (e) {
console.log("Exception when calling a 'brackets done loading' handler");
console.log(e);
}
}

function _onBracketsReady() {
var i;
bracketsReady = true;
for (i = 0; i < bracketsReadyHandlers.length; i++) {
_callBracketsReadyHandler(bracketsReadyHandlers[i]);
}
bracketsReadyHandlers = [];
}

// WARNING: This event won't fire if ANY extension fails to load or throws an error during init.
// To fix this, we need to make a change to _initExtensions (filed as issue 1029)
function _registerBracketsReadyHandler(handler) {
if (bracketsReady) {
_callBracketsReadyHandler(handler);
} else {
bracketsReadyHandlers.push(handler);
}
}

// TODO: Issue 949 - the following code should be shared

function _initGlobalBrackets() {
// Define core brackets namespace if it isn't already defined
//
// We can't simply do 'brackets = {}' to define it in the global namespace because
// we're in "use strict" mode. Most likely, 'window' will always point to the global
// object when this code is running. However, in case it isn't (e.g. if we're running
// inside Node for CI testing) we use this trick to get the global object.
//
// Taken from:
// http://stackoverflow.com/questions/3277182/how-to-get-the-global-object-in-javascript
var Fn = Function, global = (new Fn("return this"))();
if (!global.brackets) {
global.brackets = {};
}

// Uncomment the following line to force all low level file i/o routines to complete
// asynchronously. This should only be done for testing/debugging.
// NOTE: Make sure this line is commented out again before committing!
//brackets.forceAsyncCallbacks = true;

// Load native shell when brackets is run in a native shell rather than the browser
// TODO: (issue #266) load conditionally
brackets.shellAPI = require("utils/ShellAPI");

brackets.inBrowser = !brackets.hasOwnProperty("fs");

brackets.platform = (global.navigator.platform === "MacIntel" || global.navigator.platform === "MacPPC") ? "mac" : "win";

// Loading extensions requires creating new require.js contexts, which requires access to the global 'require' object
// that always gets hidden by the 'require' in the AMD wrapper. We store this in the brackets object here so that
// the ExtensionLoader doesn't have to have access to the global object.
brackets.libRequire = global.require;

// Also store our current require.js context (the one that loads brackets core modules) so that extensions can use it
// Note: we change the name to "getModule" because this won't do exactly the same thing as 'require' in AMD-wrapped
// modules. The extension will only be able to load modules that have already been loaded once.
brackets.getModule = require;

// Provide a way for anyone (including code not using require) to register a handler for the brackets 'ready' event
// This event is like $(document).ready in that it will call the handler immediately if brackets is already done loading
//
// WARNING: This event won't fire if ANY extension fails to load or throws an error during init.
// To fix this, we need to make a change to _initExtensions (filed as issue 1029)
//
// TODO (issue 1034): We *could* use a $.Deferred for this, except deferred objects enter a broken
// state if any resolution callback throws an exception. Since third parties (e.g. extensions) may
// add callbacks to this, we need to be robust to exceptions
brackets.ready = _registerBracketsReadyHandler;
}

// TODO: (issue 1029) Add timeout to main extension loading promise, so that we always call this function
// Making this fix will fix a warning (search for issue 1029) related to the brackets 'ready' event.
// Making this fix will fix a warning (search for issue 1029) related to the global brackets 'ready' event.
function _initExtensions() {
// allow unit tests to override which plugin folder(s) to load
var paths = params.get("extensions") || "default,user";
Expand Down Expand Up @@ -237,7 +153,7 @@ define(function (require, exports, module) {
doneLoading : false
};

brackets.ready(function () {
LoadEvents.ready(function () {
brackets.test.doneLoading = true;
});
}
Expand Down Expand Up @@ -341,23 +257,22 @@ define(function (require, exports, module) {
var initialProjectPath = ProjectManager.getInitialProjectPath();
ProjectManager.openProject(initialProjectPath).done(function () {
_initTest();
_initExtensions().always(_onBracketsReady);

// WARNING: LoadEvents.ready won't fire if ANY extension fails to
// load or throws an error during init. To fix this, we need to
// make a change to _initExtensions (filed as issue 1029)
_initExtensions().always(LoadEvents._dispatchEvent(LoadEvents.READY));
});

// Check for updates
if (!params.get("skipUpdateCheck")) {
UpdateNotification.checkForUpdate();
}
}

// Main Brackets initialization
_initGlobalBrackets();

// Localize MainViewHTML and inject into <BODY> tag
$('body').html(Mustache.render(MainViewHTML, Strings));
// modules that depend on the HTML DOM should listen to
// the htmlContentLoadComplete event.
$(brackets).trigger("htmlContentLoadComplete");
LoadEvents._dispatchEvent(LoadEvents.HTML_CONTENT_LOAD_COMPLETE);

$(window.document).ready(_onReady);

Expand Down
2 changes: 2 additions & 0 deletions src/command/KeyBindingManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
define(function (require, exports, module) {
"use strict";

require("utils/Global");

var CommandManager = require("command/CommandManager");

/**
Expand Down
2 changes: 2 additions & 0 deletions src/file/FileUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
*/
define(function (require, exports, module) {
"use strict";

require("utils/Global");

var NativeFileSystem = require("file/NativeFileSystem").NativeFileSystem,
PerfUtils = require("utils/PerfUtils"),
Expand Down
5 changes: 3 additions & 2 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@

<!-- HTML content is dynamically loaded and rendered by brackets.js.
Any modules that depend on or modify HTML during load should
listen for the "htmlContentLoadComplete" event that is triggered from
the brackets global object before touching the dom. -->
require the "utils/LoadEvents" modules and install an event handler
for "htmlContentLoadComplete" (e.g. LoadEvents.htmlContentLoadComplete(handler))
before touching the DOM. -->

<!-- All other scripts are loaded through require. -->
<script src="thirdparty/require.js" data-main="brackets"></script>
Expand Down
7 changes: 5 additions & 2 deletions src/project/ProjectManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@
*/
define(function (require, exports, module) {
"use strict";

require("utils/Global");

// Load dependent non-module scripts
require("thirdparty/jstree_pre1.0_fix_1/jquery.jstree");

// Load dependent modules
var NativeFileSystem = require("file/NativeFileSystem").NativeFileSystem,
var LoadEvents = require("utils/LoadEvents"),
NativeFileSystem = require("file/NativeFileSystem").NativeFileSystem,
PreferencesManager = require("preferences/PreferencesManager"),
DocumentManager = require("document/DocumentManager"),
CommandManager = require("command/CommandManager"),
Expand Down Expand Up @@ -930,7 +933,7 @@ define(function (require, exports, module) {


// Initialize variables and listeners that depend on the HTML DOM
$(brackets).on("htmlContentLoadComplete", function () {
LoadEvents.htmlContentLoadComplete(function () {
$projectTreeContainer = $("#project-files-container");

$("#open-files-container").on("contentChanged", function () {
Expand Down
18 changes: 10 additions & 8 deletions src/project/SidebarView.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@
define(function (require, exports, module) {
"use strict";

var ProjectManager = require("project/ProjectManager"),
WorkingSetView = require("project/WorkingSetView"),
CommandManager = require("command/CommandManager"),
Commands = require("command/Commands"),
Strings = require("strings"),
PreferencesManager = require("preferences/PreferencesManager"),
EditorManager = require("editor/EditorManager");
var LoadEvents = require("utils/LoadEvents"),
ProjectManager = require("project/ProjectManager"),
WorkingSetView = require("project/WorkingSetView"),
CommandManager = require("command/CommandManager"),
Commands = require("command/Commands"),
Strings = require("strings"),
PreferencesManager = require("preferences/PreferencesManager"),
EditorManager = require("editor/EditorManager"),
Global = require("utils/Global");

var isSidebarClosed = false;

Expand Down Expand Up @@ -232,7 +234,7 @@ define(function (require, exports, module) {
}

// Initialize items dependent on HTML DOM
$(brackets).on("htmlContentLoadComplete", function () {
LoadEvents.htmlContentLoadComplete(function () {
$sidebar = $("#sidebar");
$sidebarMenuText = $("#menu-view-hide-sidebar span");
$sidebarResizer = $("#sidebar-resizer");
Expand Down
2 changes: 2 additions & 0 deletions src/utils/ExtensionLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
define(function (require, exports, module) {
"use strict";

require("utils/Global");

var NativeFileSystem = require("file/NativeFileSystem").NativeFileSystem,
FileUtils = require("file/FileUtils"),
Async = require("utils/Async"),
Expand Down
79 changes: 79 additions & 0 deletions src/utils/Global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2012 Adobe Systems Incorporated. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/


/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */

/**
* Initializes the global "brackets" variable and it's properties.
* Modules should not access the global.brackets object until either
* (a) the module requires this module, i.e. require("utils/Global") or
* (b) the module receives a "ready" event from the utils/LoadEvents module.
*/
define(function (require, exports, module) {
"use strict";

// Define core brackets namespace if it isn't already defined
//
// We can't simply do 'brackets = {}' to define it in the global namespace because
// we're in "use strict" mode. Most likely, 'window' will always point to the global
// object when this code is running. However, in case it isn't (e.g. if we're running
// inside Node for CI testing) we use this trick to get the global object.
//
// Taken from:
// http://stackoverflow.com/questions/3277182/how-to-get-the-global-object-in-javascript
var Fn = Function, global = (new Fn("return this"))();
if (!global.brackets) {
global.brackets = {};
}

// Uncomment the following line to force all low level file i/o routines to complete
// asynchronously. This should only be done for testing/debugging.
// NOTE: Make sure this line is commented out again before committing!
//brackets.forceAsyncCallbacks = true;

// Load native shell when brackets is run in a native shell rather than the browser
// TODO: (issue #266) load conditionally
global.brackets.shellAPI = require("utils/ShellAPI");

global.brackets.inBrowser = !global.brackets.hasOwnProperty("fs");

global.brackets.platform = (global.navigator.platform === "MacIntel" || global.navigator.platform === "MacPPC") ? "mac" : "win";

// Loading extensions requires creating new require.js contexts, which
// requires access to the global 'require' object that always gets hidden
// by the 'require' in the AMD wrapper. We store this in the brackets
// object here so that the ExtensionLoader doesn't have to have access to
// the global object.
global.brackets.libRequire = global.require;

// Also store our current require.js context (the one that loads brackets
// core modules) so that extensions can use it.
// Note: we change the name to "getModule" because this won't do exactly
// the same thing as 'require' in AMD-wrapped modules. The extension will
// only be able to load modules that have already been loaded once.
global.brackets.getModule = require;

exports.global = global;
});
Loading

0 comments on commit 20a56cb

Please sign in to comment.