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

A few improvements fixes in Recent Projects #3213

Merged
merged 2 commits into from
Apr 6, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<ul id="project-dropdown" class="dropdown-menu">
{{#projectList}}
<li>
<a class="recent-folder-link" data-path="{{path}}">
<span class="recent-folder">{{folder}}</span>
<span class="recent-folder-path">{{rest}}</span>
</a>
</li>
{{/projectList}}

{{#hasProject}}
<li class="divider"></li>
{{/hasProject}}

<li><a id="project-settings-link">{{CMD_PROJECT_SETTINGS}}</a></li>
<li><a id="open-folder-link">{{CMD_OPEN_FOLDER}}</a></li>
</ul>
129 changes: 70 additions & 59 deletions src/extensions/default/RecentProjects/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/

/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define, brackets, window, $ */
/*global define, brackets, window, $, Mustache */

define(function (require, exports, module) {
"use strict";
Expand All @@ -40,7 +40,8 @@ define(function (require, exports, module) {
Menus = brackets.getModule("command/Menus"),
PopUpManager = brackets.getModule("widgets/PopUpManager"),
FileUtils = brackets.getModule("file/FileUtils"),
NativeFileSystem = brackets.getModule("file/NativeFileSystem").NativeFileSystem;
NativeFileSystem = brackets.getModule("file/NativeFileSystem").NativeFileSystem,
ProjectsMenuTemplate = require("text!htmlContent/projects-menu.html");


var $dropdownToggle,
Expand Down Expand Up @@ -90,8 +91,9 @@ define(function (require, exports, module) {
function checkHovers(pageX, pageY) {
$dropdown.children().each(function () {
var offset = $(this).offset(),
width = $(this).outerWidth(),
width = $(this).outerWidth(),
height = $(this).outerHeight();

if (pageX >= offset.left && pageX <= offset.left + width &&
pageY >= offset.top && pageY <= offset.top + height) {
$(".recent-folder-link", this).triggerHandler("mouseenter");
Expand All @@ -110,7 +112,7 @@ define(function (require, exports, module) {

// Remove the project from the preferences.
var recentProjects = getRecentProjects(),
index = recentProjects.indexOf($(this).data("path")),
index = recentProjects.indexOf($(this).parent().data("path")),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change shouldn't be necessary since it looks like the data is actually (redundantly) set on the delete button itself in showDeleteButton(). (Did the button not work without this change? If so, would be interesting to figure out why.) That said, it seems more elegant to look it up here as you're doing, so if so, you could take out the bit in showDeleteButton() that attaches the path to the button.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to move the "x" to the template too and style it with just CSS, but I couldn't do it, so I might have missed this when going back. But it does make sense to use this and remove the data from the "x" element, so I did that, and it still works.

newProjects = [],
i;
for (i = 0; i < recentProjects.length; i++) {
Expand All @@ -121,6 +123,10 @@ define(function (require, exports, module) {
prefs.setValue("recentProjects", newProjects);
$(this).closest("li").remove();
checkHovers(e.pageX, e.pageY);

if (newProjects.length === 1) {
$dropdown.find(".divider").remove();
}
});
}

Expand Down Expand Up @@ -162,32 +168,19 @@ define(function (require, exports, module) {
hideDeleteButton();
renderDelete()
.css("top", $target.position().top + 6)
.appendTo($target)
.data("path", $target.data("path"));
.appendTo($target);
}

/**
* Create the DOM node for a single recent folder path in the dropdown menu.
* @param {string} path The full path to the folder.
* Adds the click and mouse enter/leave events to the dropdown
*/
function renderPath(path) {
var lastSlash = path.lastIndexOf("/"), folder, rest;
if (lastSlash === path.length - 1) {
lastSlash = path.slice(0, path.length - 1).lastIndexOf("/");
}
if (lastSlash >= 0) {
rest = " - " + (lastSlash ? path.slice(0, lastSlash) : "/");
folder = path.slice(lastSlash + 1);
} else {
rest = "/";
folder = path;
}

var folderSpan = $("<span class='recent-folder'></span>").text(folder),
restSpan = $("<span class='recent-folder-path'></span>").text(rest),
$link = $("<a class='recent-folder-link'></a>");
return $link.append(folderSpan).append(restSpan).data("path", path)
.click(function () {
function _handleListEvents() {
$dropdown.click(function (e) {
var $link = $(e.target).closest("a"),
id = $link.attr("id"),
path = $link.data("path");

if (path) {
ProjectManager.openProject(path)
.fail(function () {
// Remove the project from the list only if it does not exist on disk
Expand All @@ -202,56 +195,70 @@ define(function (require, exports, module) {
}
});
closeDropdown();
})

} else if (id === "project-settings-link") {
CommandManager.execute(Commands.FILE_PROJECT_SETTINGS);

} else if (id === "open-folder-link") {
CommandManager.execute(Commands.FILE_OPEN_FOLDER);
}

});

$dropdown.find(".recent-folder-link")
.mouseenter(function () {
// Note: we can't depend on the event here because this can be triggered
// manually from checkHovers().
showDeleteButton($link);
showDeleteButton($(this));
})
.mouseleave(function () {
hideDeleteButton();
});
}

/**
* Parses the path and returns an object with the full path, the folder name and the path without the folder.
* @param {string} path The full path to the folder.
* @return {{path: string, folder: string, rest: string}}
*/
function parsePath(path) {
var lastSlash = path.lastIndexOf("/"), folder, rest;
if (lastSlash === path.length - 1) {
lastSlash = path.slice(0, path.length - 1).lastIndexOf("/");
}
if (lastSlash >= 0) {
rest = " - " + (lastSlash ? path.slice(0, lastSlash) : "/");
folder = path.slice(lastSlash + 1);
} else {
rest = "/";
folder = path;
}

return {path: path, folder: folder, rest: rest};
}

/**
* Create the list of projects in the dropdown menu.
* @return {string} The html content
*/
function renderList() {
var recentProjects = getRecentProjects(),
currentProject = FileUtils.canonicalizeFolderPath(ProjectManager.getProjectRoot().fullPath),
hasProject = false;
projectList = [];

$dropdown.children().remove();

recentProjects.forEach(function (root) {
if (root !== currentProject) {
var $link = renderPath(root);
$("<li></li>")
.append($link)
.appendTo($dropdown);
hasProject = true;
projectList.push(parsePath(root));
}
});

if (hasProject) {
$("<li class='divider'>").appendTo($dropdown);
}
// Entry for project settings dialog
$("<li><a id='project-settings-link'>" + Strings.CMD_PROJECT_SETTINGS + "</a></li>")
.click(function () {
CommandManager.execute(Commands.FILE_PROJECT_SETTINGS);
})
.appendTo($dropdown);
$("<li><a id='open-folder-link'>" + Strings.CMD_OPEN_FOLDER + "</a></li>")
.click(function () {
CommandManager.execute(Commands.FILE_OPEN_FOLDER);
})
.appendTo($dropdown);
var templateVars = {projectList: projectList, hasProject: projectList.length};

return Mustache.render(ProjectsMenuTemplate, $.extend(templateVars, Strings));
}

/**
* Show or hide the recent projects dropdown.
* @param {object} e The event object that triggered the toggling.
* @param {$.Event} e The event object that triggered the toggling.
*/
function toggle(e) {
// If the dropdown is already visible, just return (so the root click handler on html
Expand All @@ -267,15 +274,16 @@ define(function (require, exports, module) {
// Have to do this stopProp to avoid the html click handler from firing when this returns.
e.stopPropagation();

$dropdown = $("<ul id='project-dropdown' class='dropdown-menu'></ul>");
renderList();
$dropdown = $(renderList());

var toggleOffset = $dropdownToggle.offset();
$dropdown.css({
left: toggleOffset.left,
top: toggleOffset.top + $dropdownToggle.outerHeight()
})
$dropdown
.css({
left: toggleOffset.left,
top: toggleOffset.top + $dropdownToggle.outerHeight()
})
.appendTo($("body"));

PopUpManager.addPopUp($dropdown, cleanupDropdown, true);

// TODO: should use capture, otherwise clicking on the menus doesn't close it. More fallout
Expand All @@ -296,11 +304,13 @@ define(function (require, exports, module) {
// Hacky: if we detect a click in the menubar, close ourselves.
// TODO: again, we should have centralized popup management.
$("#main-toolbar .nav").on("click", closeDropdown);

_handleListEvents();
}

// Initialize extension
AppInit.appReady(function () {
ExtensionUtils.loadStyleSheet(module, "styles.css");
ExtensionUtils.loadStyleSheet(module, "styles/styles.css");

$(ProjectManager).on("projectOpen", add);
$(ProjectManager).on("beforeProjectClose", add);
Expand All @@ -310,6 +320,7 @@ define(function (require, exports, module) {
$("#project-title")
.wrap("<div id='project-dropdown-toggle'></div>")
.after("<span class='dropdown-arrow'></span>");

$dropdownToggle = $("#project-dropdown-toggle").click(toggle);
});
});