Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge remote-tracking branch 'origin/master' into jasonsanjose/statusbar

  • Loading branch information...
commit 6f38c6ad2e2b4c36c92d32155544cbdda2022117 2 parents ac31db2 + 82ef833
@jasonsanjose jasonsanjose authored
View
2  src/brackets.js
@@ -270,7 +270,7 @@ define(function (require, exports, module) {
// Prevent unhandled mousedown events from triggering native behavior
// Example: activating AutoScroll when clicking the middle mouse button (see #510)
- $("html").on("mousedown", function(event) {
+ $("html").on("mousedown", function (event) {
event.preventDefault();
});
View
76 src/editor/CodeHintManager.js
@@ -73,15 +73,24 @@ define(function (require, exports, module) {
/**
* @private
- * Enters the code completion text into the editor
+ * Enters the code completion text into the editor and closes list
* @string {string} completion - text to insert into current code editor
*/
CodeHintList.prototype._handleItemClick = function (completion) {
- this.currentProvider.handleSelect(completion, this.editor, this.editor.getCursorPos());
+ this.currentProvider.handleSelect(completion, this.editor, this.editor.getCursorPos(), true);
this.close();
};
/**
+ * @private
+ * Enters the code completion text into the editor without closing list
+ * @string {string} completion - text to insert into current code editor
+ */
+ CodeHintList.prototype._handleItemSelect = function (completion) {
+ this.currentProvider.handleSelect(completion, this.editor, this.editor.getCursorPos(), false);
+ };
+
+ /**
* Adds a single item to the hint list
* @param {string} name
*/
@@ -98,6 +107,12 @@ define(function (require, exports, module) {
// bootstrap-dropdown).
e.stopPropagation();
self._handleItemClick(name);
+ })
+ .on("select", function (e) {
+ // Don't let the "select" propagate upward (otherwise it will hit the close handler in
+ // bootstrap-dropdown).
+ e.stopPropagation();
+ self._handleItemSelect(name);
});
this.$hintMenu.find("ul.dropdown-menu")
@@ -179,32 +194,39 @@ define(function (require, exports, module) {
var keyCode = event.keyCode;
// Up arrow, down arrow and enter key are always handled here
- if (event.type !== "keypress" &&
- (keyCode === KeyEvent.DOM_VK_UP || keyCode === KeyEvent.DOM_VK_DOWN || keyCode === KeyEvent.DOM_VK_RETURN ||
- keyCode === KeyEvent.DOM_VK_PAGE_UP || keyCode === KeyEvent.DOM_VK_PAGE_DOWN)) {
-
- if (event.type === "keydown") {
- if (keyCode === KeyEvent.DOM_VK_UP) {
- // Up arrow
- this.setSelectedIndex(this.selectedIndex - 1);
- } else if (keyCode === KeyEvent.DOM_VK_DOWN) {
- // Down arrow
- this.setSelectedIndex(this.selectedIndex + 1);
- } else if (keyCode === KeyEvent.DOM_VK_PAGE_UP) {
- // Page Up
- this.setSelectedIndex(this.selectedIndex - this.getItemsPerPage());
- } else if (keyCode === KeyEvent.DOM_VK_PAGE_DOWN) {
- // Page Down
- this.setSelectedIndex(this.selectedIndex + this.getItemsPerPage());
- } else {
- // Enter/return key
- // Trigger a click handler to commmit the selected item
- $(this.$hintMenu.find("li")[this.selectedIndex]).triggerHandler("click");
+ if (event.type !== "keypress") {
+
+ if (keyCode === KeyEvent.DOM_VK_UP || keyCode === KeyEvent.DOM_VK_DOWN || keyCode === KeyEvent.DOM_VK_RETURN ||
+ keyCode === KeyEvent.DOM_VK_PAGE_UP || keyCode === KeyEvent.DOM_VK_PAGE_DOWN) {
+
+ if (event.type === "keydown") {
+ if (keyCode === KeyEvent.DOM_VK_UP) {
+ // Up arrow
+ this.setSelectedIndex(this.selectedIndex - 1);
+ } else if (keyCode === KeyEvent.DOM_VK_DOWN) {
+ // Down arrow
+ this.setSelectedIndex(this.selectedIndex + 1);
+ } else if (keyCode === KeyEvent.DOM_VK_PAGE_UP) {
+ // Page Up
+ this.setSelectedIndex(this.selectedIndex - this.getItemsPerPage());
+ } else if (keyCode === KeyEvent.DOM_VK_PAGE_DOWN) {
+ // Page Down
+ this.setSelectedIndex(this.selectedIndex + this.getItemsPerPage());
+ } else {
+ // Enter/return key
+ // Trigger a click handler to commmit the selected item
+ $(this.$hintMenu.find("li")[this.selectedIndex]).triggerHandler("click");
+ }
}
+
+ event.preventDefault();
+ return;
+
+ } else if (keyCode === KeyEvent.DOM_VK_TAB) {
+ // Tab key is used for "select and continue hinting"
+ $(this.$hintMenu.find("li")[this.selectedIndex]).triggerHandler("select");
+ event.preventDefault();
}
-
- event.preventDefault();
- return;
}
// All other key events trigger a rebuild of the list, but only
@@ -420,7 +442,7 @@ define(function (require, exports, module) {
*
* @param {Object.< getQueryInfo: function(editor, cursor),
* search: function(string),
- * handleSelect: function(string, Editor, cursor),
+ * handleSelect: function(string, Editor, cursor, closeHints),
* shouldShowHintsOnKey: function(string)>}
*
* Parameter Details:
View
36 src/editor/EditorManager.js
@@ -342,27 +342,27 @@ define(function (require, exports, module) {
* @private
*/
function _doFocusedEditorChanged(current, previous) {
+ // Skip if the new editor is already the focused editor.
+ // This may happen if the window loses then regains focus.
+ if (previous === current) {
+ return;
+ }
+
+ // if switching to no-editor, hide the last full editor
+ if (_currentEditor && !current) {
+ _currentEditor.setVisible(false);
+ }
+
+ // _currentEditor must be a full editor or null (show no editor).
+ // _currentEditor must not be an inline editor
+ if (!current || (current && !current._visibleRange)) {
+ _currentEditor = current;
+ }
+
// Fire focusedEditorChange asynchronously to allow CodeMirror to
// completely update focused state. CodeMirror fires it's "onFocus"
// event prior to setting it's internal state.
window.setTimeout(function () {
- // Skip if the new editor is already the focused editor.
- // This may happen if the window loses then regains focus.
- if (previous === current) {
- return;
- }
-
- // if switching to no-editor, hide the last full editor
- if (_currentEditor && !current) {
- _currentEditor.setVisible(false);
- }
-
- // _currentEditor must be a full editor or null (show no editor).
- // _currentEditor must not be an inline editor
- if (!current || (current && !current._visibleRange)) {
- _currentEditor = current;
- }
-
// Window may have been resized since last time editor was visible, so kick it now
if (_currentEditor) {
_currentEditor.setVisible(true);
@@ -536,7 +536,7 @@ define(function (require, exports, module) {
}
}
- return _currentEditor;
+ return null;
}
/**
View
4 src/extensions/default/HTMLCodeHints/HtmlAttributes.json
@@ -138,7 +138,7 @@
"headers": { "attribOption": [] },
"height": { "attribOption": [] },
"high": { "attribOption": [] },
- "href": { "attribOption": [] },
+ "href": { "attribOption": [], "type": "url" },
"hreflang": { "attribOption": [] },
"hspace": { "attribOption": [] },
"http-equiv": { "attribOption": ["content-type", "default-style", "refresh"] },
@@ -197,7 +197,7 @@
"size": { "attribOption": [] },
"sizes": { "attribOption": ["any"] },
"span": { "attribOption": [] },
- "src": { "attribOption": [] },
+ "src": { "attribOption": [], "type": "url" },
"srcdoc": { "attribOption": [] },
"srclang": { "attribOption": [] },
"standby": { "attribOption": [] },
View
188 src/extensions/default/HTMLCodeHints/main.js
@@ -29,12 +29,17 @@ define(function (require, exports, module) {
"use strict";
// Load dependent modules
- var HTMLUtils = brackets.getModule("language/HTMLUtils"),
- HTMLTags = require("text!HtmlTags.json"),
- HTMLAttributes = require("text!HtmlAttributes.json"),
- CodeHintManager = brackets.getModule("editor/CodeHintManager"),
- tags = JSON.parse(HTMLTags),
- attributes = JSON.parse(HTMLAttributes);
+ var CodeHintManager = brackets.getModule("editor/CodeHintManager"),
+ DocumentManager = brackets.getModule("document/DocumentManager"),
+ EditorManager = brackets.getModule("editor/EditorManager"),
+ HTMLUtils = brackets.getModule("language/HTMLUtils"),
+ NativeFileSystem = brackets.getModule("file/NativeFileSystem").NativeFileSystem,
+ ProjectManager = brackets.getModule("project/ProjectManager"),
+ StringUtils = brackets.getModule("utils/StringUtils"),
+ HTMLTags = require("text!HtmlTags.json"),
+ HTMLAttributes = require("text!HtmlAttributes.json"),
+ tags = JSON.parse(HTMLTags),
+ attributes = JSON.parse(HTMLAttributes);
/**
* @constructor
@@ -88,8 +93,9 @@ define(function (require, exports, module) {
* @param {string} completion - text to insert into current code editor
* @param {Editor} editor
* @param {Cursor} current cursor location
+ * @param {boolean} closeHints - true to close hints, or false to continue hinting
*/
- TagHints.prototype.handleSelect = function (completion, editor, cursor) {
+ TagHints.prototype.handleSelect = function (completion, editor, cursor, closeHints) {
var start = {line: -1, ch: -1},
end = {line: -1, ch: -1},
tagInfo = HTMLUtils.getTagInfo(editor, cursor),
@@ -126,6 +132,7 @@ define(function (require, exports, module) {
*/
function AttrHints() {
this.globalAttributes = this.readGlobalAttrHints();
+ this.cachedHints = null;
}
/**
@@ -146,8 +153,9 @@ define(function (require, exports, module) {
* @param {string} completion - text to insert into current code editor
* @param {Editor} editor
* @param {Cursor} current cursor location
+ * @param {boolean} closeHints - true to close hints, or false to continue hinting
*/
- AttrHints.prototype.handleSelect = function (completion, editor, cursor) {
+ AttrHints.prototype.handleSelect = function (completion, editor, cursor, closeHints) {
var start = {line: -1, ch: -1},
end = {line: -1, ch: -1},
tagInfo = HTMLUtils.getTagInfo(editor, cursor),
@@ -195,15 +203,17 @@ define(function (require, exports, module) {
}
}
- if (insertedName) {
- editor.setCursorPos(start.line, start.ch + completion.length - 1);
-
- // Since we're now inside the double-quotes we just inserted,
- // mmediately pop up the attribute value hint.
- CodeHintManager.showHint(editor);
- } else if (tokenType === HTMLUtils.ATTR_VALUE && tagInfo.attr.hasEndQuote) {
- // Move the cursor to the right of the existing end quote after value insertion.
- editor.setCursorPos(start.line, start.ch + completion.length + 1);
+ if (closeHints) {
+ if (insertedName) {
+ editor.setCursorPos(start.line, start.ch + completion.length - 1);
+
+ // Since we're now inside the double-quotes we just inserted,
+ // immediately pop up the attribute value hint.
+ CodeHintManager.showHint(editor);
+ } else if (tokenType === HTMLUtils.ATTR_VALUE && tagInfo.attr.hasEndQuote) {
+ // Move the cursor to the right of the existing end quote after value insertion.
+ editor.setCursorPos(start.line, start.ch + completion.length + 1);
+ }
}
};
@@ -247,6 +257,141 @@ define(function (require, exports, module) {
};
/**
+ * Helper function for search(). Create a list of urls to existing files based on the query.
+ * @param {Object.<queryStr: string, ...} query -- a query object with a required property queryStr
+ * that will be used to filter out code hints
+ * @return {Array.<string>}
+ */
+ AttrHints.prototype._getUrlList = function (query) {
+ var doc,
+ result = [];
+
+ // site-root relative links are not yet supported, so filter them out
+ if (query.queryStr.length > 0 && query.queryStr[0] === "/") {
+ return result;
+ }
+
+ // get path to current document
+ doc = DocumentManager.getCurrentDocument();
+ if (!doc || !doc.file) {
+ return result;
+ }
+
+ var docUrl = window.PathUtils.parseUrl(doc.file.fullPath);
+ if (!docUrl) {
+ return result;
+ }
+
+ var docDir = docUrl.domain + docUrl.directory;
+
+ // get relative path from query string
+ // TODO: handle site-root relative
+ var queryDir = "";
+ var queryUrl = window.PathUtils.parseUrl(query.queryStr);
+ if (queryUrl) {
+ queryDir = queryUrl.directory;
+ }
+
+ // build target folder path
+ var targetDir = docDir + decodeURI(queryDir);
+
+ // get list of files from target folder
+ var unfiltered = [];
+
+ // Getting the file/folder info is an asynch operation, so it works like this:
+ //
+ // The initial pass initiates the asynchronous retrieval of data and returns an
+ // empty list, so no code hints are displayed. In the async callback, the code
+ // hints and the original query are stored in a cache, and then the process to
+ // show code hints is re-initiated.
+ //
+ // During the next pass, there should now be code hints cached from the initial
+ // pass, but user may have typed while file/folder info was being retrieved from
+ // disk, so we need to make sure code hints still apply to current query. If so,
+ // display them, otherwise, clear cache and start over.
+ //
+ // As user types within a folder, the same unfiltered file/folder list is still
+ // valid and re-used from cache. Filtering based on user input is done outside
+ // of this method. When user moves to a new folder, then the cache is deleted,
+ // and file/folder info for new folder is then retrieved.
+
+ if (this.cachedHints) {
+ // url hints have been cached, so determine if they're stale
+ if (!this.cachedHints.query ||
+ this.cachedHints.query.tag !== query.tag ||
+ this.cachedHints.query.attrName !== query.attrName ||
+ this.cachedHints.queryDir !== queryDir) {
+
+ // delete stale cache
+ this.cachedHints = null;
+ }
+ }
+
+ if (this.cachedHints) {
+ // use cached hints
+ unfiltered = this.cachedHints.unfiltered;
+
+ } else {
+ var self = this,
+ origEditor = EditorManager.getFocusedEditor();
+
+ // create empty object so we can detect "waiting" state
+ self.cachedHints = {};
+ self.cachedHints.unfiltered = [];
+
+ NativeFileSystem.requestNativeFileSystem(targetDir, function (dirEntry) {
+ dirEntry.createReader().readEntries(function (entries) {
+
+ entries.forEach(function (entry) {
+ if (ProjectManager.shouldShow(entry)) {
+ // convert to doc relative path
+ var entryStr = entry.fullPath.replace(docDir, "");
+
+ // code hints show the same strings that are inserted into text,
+ // so strings in list will be encoded. wysiwyg, baby!
+ unfiltered.push(encodeURI(entryStr));
+ }
+ });
+
+ self.cachedHints.unfiltered = unfiltered;
+ self.cachedHints.query = query;
+ self.cachedHints.queryDir = queryDir;
+
+ // If the editor has not changed, then re-initiate code hints. Cached data
+ // is still valid for folder even if we're not going to show it now.
+ if (origEditor === EditorManager.getFocusedEditor()) {
+ CodeHintManager.showHint(origEditor);
+ }
+ });
+ });
+
+ return result;
+ }
+
+ // build list
+
+ // without these entries, typing "../" will not display entries for containing folder
+ if (queryUrl.filename === ".") {
+ result.push(queryDir + ".");
+ } else if (queryUrl.filename === "..") {
+ result.push(queryDir + "..");
+ }
+
+ // add file/folder entries
+ unfiltered.forEach(function (item) {
+ result.push(item);
+ });
+
+ // TODO: filter by desired file type based on tag, type attr, etc.
+
+ // TODO: add list item to top of list to popup modal File Finder dialog
+ // New string: "Browse..." or "Choose a File..."
+ // Command: Commands.FILE_OPEN
+
+ return result;
+ };
+
+ /**
* Create a complete list of attributes for the tag in the query. Then filter
* the list by attrName in the query and return the result.
* @param {Object.<queryStr: string, ...} query -- a query object with a required property queryStr
@@ -260,7 +405,8 @@ define(function (require, exports, module) {
var tagName = query.tag,
attrName = query.attrName,
filter = query.queryStr,
- unfiltered = [];
+ unfiltered = [],
+ sortFunc = null;
if (attrName) {
// We look up attribute values with tagName plus a slash and attrName first.
@@ -274,6 +420,9 @@ define(function (require, exports, module) {
if (attrInfo) {
if (attrInfo.type === "boolean") {
unfiltered = ["false", "true"];
+ } else if (attrInfo.type === "url") {
+ unfiltered = this._getUrlList(query);
+ sortFunc = StringUtils.urlSort;
} else if (attrInfo.attribOption) {
unfiltered = attrInfo.attribOption;
}
@@ -285,11 +434,12 @@ define(function (require, exports, module) {
}
if (unfiltered.length) {
+ console.assert(!result.length);
result = $.map(unfiltered, function (item) {
if (item.indexOf(filter) === 0) {
return item;
}
- }).sort();
+ }).sort(sortFunc);
}
}
View
4 src/nls/de/strings.js
@@ -231,8 +231,8 @@ define({
"APP_NAME" : "xBrackets",
"CLOSE" : "Schließen",
"ABOUT_TEXT_LINE1" : "Sprint 15 experimenteller Build ",
- "ABOUT_TEXT_LINE3" : "Hinweise, Bestimmungen und Bedingungen, die sich auf Drittanbieter-Software beziehen, finden sich unter <span class=\"non-clickble-link\">http://www.adobe.com/go/thirdparty/</span> und sind hier durch Bezugnahme eingeschlossen.",
- "ABOUT_TEXT_LINE4" : "Dokumentation und Quellcode unter <span class=\"non-clickble-link\">https://github.com/adobe/brackets/</span>",
+ "ABOUT_TEXT_LINE3" : "Hinweise, Bestimmungen und Bedingungen, die sich auf Drittanbieter-Software beziehen, finden sich unter <a class=\"clickable-link\" data-href=\"http://www.adobe.com/go/thirdparty/\">http://www.adobe.com/go/thirdparty/</a> und sind hier durch Bezugnahme eingeschlossen.",
+ "ABOUT_TEXT_LINE4" : "Dokumentation und Quellcode unter <a class=\"clickable-link\" data-href=\"https://github.com/adobe/brackets/\">https://github.com/adobe/brackets/</a>",
"UPDATE_NOTIFICATION_TOOLTIP" : "Eine neue Version von {APP_NAME} ist verfügbar! Für Details hier klicken.",
"UPDATE_AVAILABLE_TITLE" : "Update verfügbar",
"UPDATE_MESSAGE" : "Hallo! Eine neue Version von {APP_NAME} ist verfügbar. Hier einige der neuen Funktionen:",
View
4 src/nls/es/strings.js
@@ -214,8 +214,8 @@ define({
"APP_NAME" : "{APP_NAME}",
"CLOSE" : "Cerrar",
"ABOUT_TEXT_LINE1" : "sprint 15 versión experimental ",
- "ABOUT_TEXT_LINE3" : "Los avisos, términos y condiciones pertenecientes a software de terceros se encuentran en <span class=\"non-clickble-link\">http://www.adobe.com/go/thirdparty/</span> y se incluyen aquí como referencia.",
- "ABOUT_TEXT_LINE4" : "Puedes encontrar la documentación y código fuente en <span class=\"non-clickble-link\">https://github.com/adobe/brackets/</span>",
+ "ABOUT_TEXT_LINE3" : "Los avisos, términos y condiciones pertenecientes a software de terceros se encuentran en <a class=\"clickable-link\" data-href=\"http://www.adobe.com/go/thirdparty/\">http://www.adobe.com/go/thirdparty/</a> y se incluyen aquí como referencia.",
+ "ABOUT_TEXT_LINE4" : "Puedes encontrar la documentación y código fuente en <a class=\"clickable-link\" data-href=\"https://github.com/adobe/brackets/\">https://github.com/adobe/brackets/</a>",
"UPDATE_NOTIFICATION_TOOLTIP" : "¡Hay una nueva versión de {APP_NAME} disponible! Haz click aquí para más detalles.",
"UPDATE_AVAILABLE_TITLE" : "Actualización disponible",
"UPDATE_MESSAGE" : "Oye, hay una nueva versión de {APP_NAME} disponible. Éstas son algunas de las nuevas características:",
View
4 src/nls/fr/strings.js
@@ -223,8 +223,8 @@ define({
"APP_NAME": "Brackets",
"CLOSE": "Fermer",
"ABOUT_TEXT_LINE1": "version expérimentale sprint 14 ",
- "ABOUT_TEXT_LINE3": "Les mentions légales et conditions générales relatives aux logiciels tiers sont disponibles (en anglais) à l’adresse <span class=\"non-clickble-link\">http://www.adobe.com/go/thirdparty_fr/</span> et sont incluses dans le présent document à titre de référence.",
- "ABOUT_TEXT_LINE4": "La documentation et le code source sont disponibles à l’adresse <span class=\"non-clickble-link\">https://github.com/adobe/brackets/</span>",
+ "ABOUT_TEXT_LINE3": "Les mentions légales et conditions générales relatives aux logiciels tiers sont disponibles (en anglais) à l’adresse <a class=\"clickable-link\" data-href=\"http://www.adobe.com/go/thirdparty_fr/\">http://www.adobe.com/go/thirdparty_fr/</a> et sont incluses dans le présent document à titre de référence.",
+ "ABOUT_TEXT_LINE4": "La documentation et le code source sont disponibles à l’adresse <a class=\"clickable-link\" data-href=\"https://github.com/adobe/brackets/\">https://github.com/adobe/brackets/</a>",
"UPDATE_NOTIFICATION_TOOLTIP": "Une nouvelle version de {APP_NAME} est disponible. Cliquez ici pour plus de détails.",
"UPDATE_AVAILABLE_TITLE": "Mise à jour disponible",
"UPDATE_MESSAGE": "Une nouvelle version de {APP_NAME} est disponible. Voici quelques-unes des nouvelles fonctionnalités proposées :",
View
4 src/nls/it/strings.js
@@ -214,8 +214,8 @@ define({
"APP_NAME" : "Brackets",
"CLOSE" : "Chiudi",
"ABOUT_TEXT_LINE1" : "sprint 14 build sperimentale",
- "ABOUT_TEXT_LINE3" : "Avvisi, termini e condizioni pertinenti software di terze parti sono disponibili all'indirizzo <span class=\"non-clickble-link\">http://www.adobe.com/go/thirdparty/</span> e incorporati per riferimento in questo documento.",
- "ABOUT_TEXT_LINE4" : "Documentazione e codice sorgente sono disponibili all'indirizzo <span class=\"non-clickble-link\">https://github.com/adobe/brackets/</span>",
+ "ABOUT_TEXT_LINE3" : "Avvisi, termini e condizioni pertinenti software di terze parti sono disponibili all'indirizzo <a class=\"clickable-link\" data-href=\"http://www.adobe.com/go/thirdparty/\">http://www.adobe.com/go/thirdparty/</a> e incorporati per riferimento in questo documento.",
+ "ABOUT_TEXT_LINE4" : "Documentazione e codice sorgente sono disponibili all'indirizzo <a class=\"clickable-link\" data-href=\"https://github.com/adobe/brackets/\">https://github.com/adobe/brackets/</a>",
"UPDATE_NOTIFICATION_TOOLTIP" : "E' disponibile una nuova versione di {APP_NAME}! Clicca qui per i dettagli.",
"UPDATE_AVAILABLE_TITLE" : "Aggiornamento disponibile",
"UPDATE_MESSAGE" : "Hey, è disponibile una nuova versione di {APP_NAME}. Nuove caratteristiche:",
View
4 src/nls/nb/strings.js
@@ -222,8 +222,8 @@ define({
"APP_NAME" : "Brackets",
"CLOSE" : "Lukk",
"ABOUT_TEXT_LINE1" : "sprint 15 experimental build ",
- "ABOUT_TEXT_LINE3": "Notices, terms and conditions pertaining to third party software are located at <span class=\"non-clickble-link\">http://www.adobe.com/go/thirdparty/</span> and incorporated by reference herein.",
- "ABOUT_TEXT_LINE4" : "Documentation and source at <span class=\"non-clickble-link\">https://github.com/adobe/brackets/</span>",
+ "ABOUT_TEXT_LINE3" : "Notices, terms and conditions pertaining to third party software are located at <a class=\"clickable-link\" data-href=\"http://www.adobe.com/go/thirdparty/\">http://www.adobe.com/go/thirdparty/</a> and incorporated by reference herein.",
+ "ABOUT_TEXT_LINE4" : "Documentation and source at <a class=\"clickable-link\" data-href=\"https://github.com/adobe/brackets/\">https://github.com/adobe/brackets/</a>",
"UPDATE_NOTIFICATION_TOOLTIP" : "En ny for {APP_NAME} er tilgjengelig! Klikk her for mer informasjon.",
"UPDATE_AVAILABLE_TITLE" : "Oppdatering er tilgjengelig",
"UPDATE_MESSAGE" : "Hei, en ny bygg for {APP_NAME} er tilgjengelig. Her er noen av de nye funksjonene:",
View
4 src/nls/root/strings.js
@@ -241,8 +241,8 @@ define({
"APP_NAME" : "Brackets",
"CLOSE" : "Close",
"ABOUT_TEXT_LINE1" : "sprint 15 experimental build ",
- "ABOUT_TEXT_LINE3" : "Notices, terms and conditions pertaining to third party software are located at <span class=\"non-clickble-link\">http://www.adobe.com/go/thirdparty/</span> and incorporated by reference herein.",
- "ABOUT_TEXT_LINE4" : "Documentation and source at <span class=\"non-clickble-link\">https://github.com/adobe/brackets/</span>",
+ "ABOUT_TEXT_LINE3" : "Notices, terms and conditions pertaining to third party software are located at <a class=\"clickable-link\" data-href=\"http://www.adobe.com/go/thirdparty/\">http://www.adobe.com/go/thirdparty/</a> and incorporated by reference herein.",
+ "ABOUT_TEXT_LINE4" : "Documentation and source at <a class=\"clickable-link\" data-href=\"https://github.com/adobe/brackets/\">https://github.com/adobe/brackets/</a>",
"UPDATE_NOTIFICATION_TOOLTIP" : "There's a new build of {APP_NAME} available! Click here for details.",
"UPDATE_AVAILABLE_TITLE" : "Update Available",
"UPDATE_MESSAGE" : "Hey, there's a new build of {APP_NAME} available. Here are some of the new features:",
View
2  src/project/ProjectManager.js
@@ -513,7 +513,7 @@ define(function (require, exports, module) {
/** @param {Entry} entry File or directory to filter */
function shouldShow(entry) {
- return [".git", ".svn", ".DS_Store", "Thumbs.db"].indexOf(entry.name) === -1;
+ return [".git", ".gitignore", ".gitmodules", ".svn", ".DS_Store", "Thumbs.db"].indexOf(entry.name) === -1;
}
/**
View
2  src/search/FindInFiles.js
@@ -215,7 +215,7 @@ define(function (require, exports, module) {
// Add row for file name
$("<tr class='file-section' />")
- .append("<td colspan='3'>" + StringUtils.format(Strings.FIND_IN_FILES_FILE_PATH, item.fullPath) + "</td>")
+ .append("<td colspan='3'>" + StringUtils.format(Strings.FIND_IN_FILES_FILE_PATH, StringUtils.breakableUrl(item.fullPath)) + "</td>")
.click(function () {
// Clicking file section header collapses/expands result rows for that file
var $fileHeader = $(this);
View
2  src/search/QuickOpen.js
@@ -569,7 +569,7 @@ define(function (require, exports, module) {
// Use the filename formatter
query = StringUtils.htmlEscape(query);
var displayName = StringUtils.htmlEscape(item.label);
- var displayPath = StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(item.fullPath));
+ var displayPath = StringUtils.breakableUrl(StringUtils.htmlEscape(ProjectManager.makeProjectRelativeIfPossible(item.fullPath)));
if (query.length > 0) {
// make the user's query bold within the item's text
View
4 src/styles/brackets.less
@@ -707,3 +707,7 @@ ins.jstree-icon {
li.smart_autocomplete_highlight {
background-color: #e0f0fa;
}
+
+.clickable-link {
+ cursor: pointer;
+}
View
39 src/utils/StringUtils.js
@@ -22,7 +22,7 @@
*/
/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
-/*global define, $ */
+/*global define, $, brackets */
/**
* Utilities functions related to string manipulation
@@ -119,6 +119,41 @@ define(function (require, exports, module) {
}
}
+ function urlSort(a, b) {
+ var a2, b2;
+ function isFile(s) {
+ return ((s.lastIndexOf("/") + 1) < s.length);
+ }
+
+ if (brackets.platform === "win") {
+ // Windows: prepend folder names with a '0' and file names with a '1' so folders are listed first
+ a2 = ((isFile(a)) ? "1" : "0") + a.toLowerCase();
+ b2 = ((isFile(b)) ? "1" : "0") + b.toLowerCase();
+ } else {
+ a2 = a.toLowerCase();
+ b2 = b.toLowerCase();
+ }
+
+ if (a2 === b2) {
+ return 0;
+ } else {
+ return (a2 > b2) ? 1 : -1;
+ }
+ }
+
+ /**
+ * Return a path or URL string that can be broken near path separators.
+ * @param {string} url the path or URL to format
+ * @return {string} the formatted path or URL
+ */
+ function breakableUrl(url) {
+ // Inject zero-width space character (U+200B) near path separators (/) to allow line breaking there
+ return url.replace(
+ new RegExp(regexEscape("/"), "g"),
+ "/" + "&#8203;"
+ );
+ }
+
// Define public API
exports.format = format;
exports.htmlEscape = htmlEscape;
@@ -126,4 +161,6 @@ define(function (require, exports, module) {
exports.jQueryIdEscape = jQueryIdEscape;
exports.getLines = getLines;
exports.offsetToLineNum = offsetToLineNum;
+ exports.urlSort = urlSort;
+ exports.breakableUrl = breakableUrl;
});
View
11 src/widgets/Dialogs.js
@@ -34,7 +34,8 @@ define(function (require, exports, module) {
require("utils/Global");
var KeyBindingManager = require("command/KeyBindingManager"),
- KeyEvent = require("utils/KeyEvent");
+ KeyEvent = require("utils/KeyEvent"),
+ NativeApp = require("utils/NativeApp");
var DIALOG_BTN_CANCEL = "cancel",
DIALOG_BTN_OK = "ok",
@@ -55,6 +56,7 @@ define(function (require, exports, module) {
function _dismissDialog(dlg, buttonId) {
dlg.data("buttonId", buttonId);
+ $(".clickable-link", dlg).off("click");
dlg.modal(true).hide();
}
@@ -154,6 +156,13 @@ define(function (require, exports, module) {
$(".dialog-message", $dlg).html(message);
}
+ $(".clickable-link", $dlg).on("click", function _handleLink(e) {
+ // Links use data-href (not href) attribute so Brackets itself doesn't redirect
+ if (e.target.dataset && e.target.dataset.href) {
+ NativeApp.openURLInDefaultBrowser(e.target.dataset.href);
+ }
+ });
+
var handleKeyDown = _handleKeyDown.bind($dlg);
// Pipe dialog-closing notification back to client code
Please sign in to comment.
Something went wrong with that request. Please try again.