Skip to content

Commit

Permalink
Merge pull request #2 from britco/escape-strings
Browse files Browse the repository at this point in the history
Escape markup
  • Loading branch information
pdufour committed Feb 12, 2015
2 parents 245b230 + 7f9e52c commit ec4daa8
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 15 deletions.
85 changes: 79 additions & 6 deletions dist/form-helpers-latest.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,19 @@ $(document).ready(function() {
}
}
return dest;
}, markupEscapeCodes = {
"&": "&",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#39;",
"/": "&#x2F;"
};
function escapeMarkup(subject) {
return subject.replace(/[&<>"'\/]/g, function(char) {
return markupEscapeCodes[char];
});
}
function debounce(func, wait, immediate) {
var timeout;
return function() {
Expand All @@ -59,6 +71,64 @@ $(document).ready(function() {
}
return arr;
};
function mapKeyPressToActualCharacter(isShiftKey, characterCode) {
if (characterCode === 27 || characterCode === 8 || characterCode === 9 || characterCode === 20 || characterCode === 16 || characterCode === 17 || characterCode === 91 || characterCode === 13 || characterCode === 92 || characterCode === 18) {
return false;
}
if (typeof isShiftKey != "boolean" || typeof characterCode != "number") {
return false;
}
var _to_ascii = {
"188": "44",
"109": "45",
"190": "46",
"191": "47",
"192": "96",
"220": "92",
"222": "39",
"221": "93",
"219": "91",
"173": "45",
"187": "61",
"186": "59",
"189": "45"
};
var shiftUps = {
"96": "~",
"49": "!",
"50": "@",
"51": "#",
"52": "$",
"53": "%",
"54": "^",
"55": "&",
"56": "*",
"57": "(",
"48": ")",
"45": "_",
"61": "+",
"91": "{",
"93": "}",
"92": "|",
"59": ":",
"39": '"',
"44": "<",
"46": ">",
"47": "?"
};
if (characterCode in _to_ascii) {
characterCode = _to_ascii[characterCode];
}
var character;
if (!isShiftKey && (characterCode >= 65 && characterCode <= 90)) {
character = String.fromCharCode(characterCode + 32);
} else if (isShiftKey && shiftUps.hasOwnProperty(characterCode)) {
character = shiftUps[characterCode];
} else {
character = String.fromCharCode(characterCode);
}
return character;
}
var defaultConfig = {
selector: '.input.input-select:not([data-fancy-dropdowns="off"]) select',
beforeActive: '<div class="icon-ui-dropdown-arrow"></div>',
Expand Down Expand Up @@ -108,8 +178,8 @@ $(document).ready(function() {
ctx.selected = value;
var label = $active.html();
html += '<div class="select-active"';
html += 'data-value="' + value + '"';
html += 'data-label="' + label + '">';
html += ' data-value="' + escapeMarkup(value) + '"';
html += ' data-label="' + escapeMarkup(label) + '">';
html += config.beforeActive || "";
html += label + "</div>";
html += '<ul class="select-options dropdown-options" style="';
Expand All @@ -123,8 +193,8 @@ $(document).ready(function() {
var label = $option.html();
var labelSlug = label.trim().toLowerCase();
ctx.labels.push(labelSlug);
html += '<li class="select-option" data-value="' + value + '" data-label="' + label + '"';
html += ' data-label-slug="' + labelSlug + '">' + label + "</li>";
html += '<li class="select-option" data-value="' + escapeMarkup(value) + '" data-label="' + escapeMarkup(label) + '"';
html += ' data-label-slug="' + escapeMarkup(labelSlug) + '">' + label + "</li>";
});
html += "</ul>";
html += "</div>";
Expand Down Expand Up @@ -233,7 +303,10 @@ $(document).ready(function() {
$(document).on("keyup" + ctx.ns + "active", function(e) {
window.clearTimeout(ctx.updateAndCloseTimeout);
ctx.search_term = ctx.search_term || "";
ctx.search_term += String.fromCharCode(e.keyCode).toLowerCase();
var character = mapKeyPressToActualCharacter(e.shiftKey, e.keyCode);
if (character != null && character != false) {
ctx.search_term += (character + "").toLowerCase();
}
debounce(function() {
selectSearch.call(this, ctx);
}, 15)();
Expand Down Expand Up @@ -289,7 +362,7 @@ $(document).ready(function() {
}
function selectSearch(ctx) {
var searchTerm = ctx.search_term.trim();
var match = ctx.$options.find('> li[data-label-slug^="' + searchTerm + '"]').first();
var match = ctx.$options.find('> li[data-label-slug^="' + escapeMarkup(searchTerm) + '"], > li[data-label-slug^="' + searchTerm + '"]').first();
if (match.length) {
selectUpdateHover(ctx, match);
if (Element.prototype.scrollIntoViewIfNeeded) {
Expand Down
108 changes: 99 additions & 9 deletions src/fancy_dropdowns.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,23 @@ $(document).ready(function() {
}

return dest;
},

markupEscapeCodes = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;'
};

function escapeMarkup(subject) {
return subject.replace(/[&<>"'\/]/g, function (char) {
return markupEscapeCodes[char];
});
}

function debounce(func, wait, immediate) {
var timeout;
return function() {
Expand All @@ -38,7 +53,75 @@ $(document).ready(function() {
}
}
return arr;
};
}

// See http://stackoverflow.com/a/4786582/2763703 and
// http://stackoverflow.com/a/13127566/2763703
function mapKeyPressToActualCharacter(isShiftKey, characterCode) {
if (characterCode === 27 || characterCode === 8 || characterCode === 9 || characterCode === 20 || characterCode === 16 || characterCode === 17 || characterCode === 91 || characterCode === 13 || characterCode === 92 || characterCode === 18) {
return false;
}

if (typeof isShiftKey != "boolean" || typeof characterCode != "number") {
return false;
}

var _to_ascii = {
'188': '44',
'109': '45',
'190': '46',
'191': '47',
'192': '96',
'220': '92',
'222': '39',
'221': '93',
'219': '91',
'173': '45',
'187': '61', //IE Key codes
'186': '59', //IE Key codes
'189': '45' //IE Key codes
};

var shiftUps = {
"96": "~",
"49": "!",
"50": "@",
"51": "#",
"52": "$",
"53": "%",
"54": "^",
"55": "&",
"56": "*",
"57": "(",
"48": ")",
"45": "_",
"61": "+",
"91": "{",
"93": "}",
"92": "|",
"59": ":",
"39": "\"",
"44": "<",
"46": ">",
"47": "?"
};

if (characterCode in _to_ascii) {
characterCode = _to_ascii[characterCode];
}

var character;

if (!isShiftKey && (characterCode >= 65 && characterCode <= 90)) {
character = String.fromCharCode(characterCode + 32);
} else if (isShiftKey && shiftUps.hasOwnProperty(characterCode)) {
character = shiftUps[characterCode];
} else {
character = String.fromCharCode(characterCode);
}

return character;
}

// Config
var defaultConfig = {
Expand Down Expand Up @@ -118,8 +201,8 @@ $(document).ready(function() {
var label = $active.html();

html += '<div class="select-active"';
html += 'data-value="'+ value + '"';
html += 'data-label="'+ label +'">';
html += ' data-value="'+ escapeMarkup(value) + '"';
html += ' data-label="'+ escapeMarkup(label) +'">';
html += (config.beforeActive || '');
html += label + '</div>';

Expand All @@ -134,12 +217,11 @@ $(document).ready(function() {
var $option = $(option);
var value = $option.attr('value');

// TODO: Escape quotes when in the data-label tag
var label = $option.html();
var labelSlug = label.trim().toLowerCase();
ctx.labels.push(labelSlug);
html += '<li class="select-option" data-value="'+ value +'" data-label="'+ label +'"';
html += ' data-label-slug="' + labelSlug + '">' + label + '</li>';
html += '<li class="select-option" data-value="'+ escapeMarkup(value) +'" data-label="'+ escapeMarkup(label) +'"';
html += ' data-label-slug="' + escapeMarkup(labelSlug) + '">' + label + '</li>';
});

html += '</ul>';
Expand Down Expand Up @@ -308,7 +390,10 @@ $(document).ready(function() {
window.clearTimeout(ctx.updateAndCloseTimeout);

ctx.search_term = ctx.search_term || '';
ctx.search_term += String.fromCharCode(e.keyCode).toLowerCase();
var character = mapKeyPressToActualCharacter(e.shiftKey, e.keyCode);
if(character != null && character != false) {
ctx.search_term += (character + '').toLowerCase();
}

// Do a new search
debounce(function() {
Expand Down Expand Up @@ -388,10 +473,15 @@ $(document).ready(function() {
// If there is a matching term, focus on it
function selectSearch(ctx) {
var searchTerm = ctx.search_term.trim();
// You shouldn't need to search for escaped and non-escaped, but you do..
// some things like > will match when escaped, but double quotes will only
// match when unescaped
var match = ctx.$options
.find('> li[data-label-slug^="' + searchTerm + '"]')
.find(
'> li[data-label-slug^="' + escapeMarkup(searchTerm) + '"],\
> li[data-label-slug^="' + searchTerm + '"]'
)
.first();

if(match.length) {
// Update the hover state to the new LI
selectUpdateHover(ctx,match);
Expand Down
43 changes: 43 additions & 0 deletions test/specialchars.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../bower_components/every-insert/dist/every-insert-latest.js"></script>
<script src="../dist/form-helpers-latest.js"></script>
<style>
ul {
padding: 0;
margin: 0;
}
.select-wrapper {
border: 1px solid black;
}

.select-active {
border: 1px solid orange;
}

li.hover {
color: red;
}

li.active,li:active {
color: blue;
}

.select-wrapper-open .select-options {
max-height: 300px !important;
overflow: scroll !important;
}
</style>
</head>
<body>
<div class="input input-select" style="float: left">
<select name="size">
<option value="az">az</option>
<option value="&quot;">&quot;</option>
<option value="&#39;">&#39;</option>
<option value="&gt;">&gt;</option>
</select>
</div>
</body>
</html>

0 comments on commit ec4daa8

Please sign in to comment.