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

HTML attributes code hinting filter #2263

Merged
merged 7 commits into from
Dec 6, 2012
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
20 changes: 11 additions & 9 deletions src/extensions/default/HTMLCodeHints/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ define(function (require, exports, module) {
query.attrName = tagInfo.attr.name;
}

// TODO: get existing attributes for the current tag and add them to query.usedAttr
query.usedAttr = HTMLUtils.getTagAttributes(editor, cursor);
}

return query;
Expand Down Expand Up @@ -425,6 +425,7 @@ define(function (require, exports, module) {
attrName = query.attrName,
filter = query.queryStr,
unfiltered = [],
hints = [],
sortFunc = null;

this.closeOnSelect = true;
Expand All @@ -440,25 +441,26 @@ define(function (require, exports, module) {

if (attrInfo) {
if (attrInfo.type === "boolean") {
unfiltered = ["false", "true"];
hints = ["false", "true"];
} else if (attrInfo.type === "url") {
// Default behavior for url hints is do not close on select.
this.closeOnSelect = false;
unfiltered = this._getUrlList(query);
hints = this._getUrlList(query);
sortFunc = StringUtils.urlSort;
} else if (attrInfo.attribOption) {
unfiltered = attrInfo.attribOption;
hints = attrInfo.attribOption;
}
}
} else if (tags && tags[tagName] && tags[tagName].attributes) {
unfiltered = tags[tagName].attributes.concat(this.globalAttributes);

// TODO: exclude existing attributes from unfiltered array
hints = $.grep(unfiltered, function (attr, i) {
return $.inArray(attr, query.usedAttr) < 0;
});
}

if (unfiltered.length) {
if (hints.length) {
console.assert(!result.length);
result = $.map(unfiltered, function (item) {
result = $.map(hints, function (item) {
if (item.indexOf(filter) === 0) {
return item;
}
Expand Down
40 changes: 40 additions & 0 deletions src/language/HTMLUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,45 @@ define(function (require, exports, module) {
return null;
}

/**
* Compiles a list of used attributes for a given tag
* @param {CodeMirror} editor An instance of a CodeMirror editor
* @param {ch:{string}, line:{number}} pos A CodeMirror position
* @return {Array.<string>} A list of the used attributes inside the current tag
*/
function getTagAttributes(editor, pos) {
var attrs = [],
backwardCtx = TokenUtils.getInitialContext(editor._codeMirror, pos),
forwardCtx = $.extend({}, backwardCtx);

if (editor.getModeForSelection() === "html") {
if (backwardCtx.token && backwardCtx.token.className !== "tag") {
while (TokenUtils.movePrevToken(backwardCtx) && backwardCtx.token.className !== "tag") {
if (backwardCtx.token.className === "attribute") {
attrs.push(backwardCtx.token.string);
}
}

while (TokenUtils.moveNextToken(forwardCtx) && forwardCtx.token.className !== "tag") {
if (forwardCtx.token.className === "attribute") {
attrs.push(forwardCtx.token.string);
} else if (forwardCtx.token.className === "error") {
// If we type the first letter of the next attribute, it comes as an error
// token. We need to double check for possible invalidated attributes.
if (forwardCtx.token.string.trim() !== "" &&
forwardCtx.token.string.indexOf("\"") === -1 &&
forwardCtx.token.string.indexOf("'") === -1 &&
forwardCtx.token.string.indexOf("=") === -1) {
attrs.push(forwardCtx.token.string);
}
}
}
}
}

return attrs;
}

/**
* Creates a tagInfo object and assures all the values are entered or are empty strings
* @param {string=} tokenType what is getting edited and should be hinted
Expand Down Expand Up @@ -450,6 +489,7 @@ define(function (require, exports, module) {
exports.ATTR_VALUE = ATTR_VALUE;

exports.getTagInfo = getTagInfo;
exports.getTagAttributes = getTagAttributes;
//The createTagInfo is really only for the unit tests so they can make the same structure to
//compare results with
exports.createTagInfo = createTagInfo;
Expand Down
Loading