Skip to content

Instantly share code, notes, and snippets.

@mariovalney
Last active January 10, 2018 15:12
Show Gist options
  • Save mariovalney/eac02d9fc9ceedfccf79acce00902029 to your computer and use it in GitHub Desktop.
Save mariovalney/eac02d9fc9ceedfccf79acce00902029 to your computer and use it in GitHub Desktop.
A simple jQuery plugin to make a input be checked against punctuation, spaces and wrong capitalized words.
(function ($) {
$.fn.humanText = function(options) {
var defaults = {}, settings = {}, app = {};
/**
* Array of default settings:
*
* - last_mark: string The mark to last line. Default is period (.);
*/
defaults = {
last_mark: '.',
};
settings = $.extend( {}, defaults, options );
app = {
original_text: '',
human_text: '',
punctuation: [';', '.', '!', '?'],
ucFirstWord: function() {
var regex = /([\.|!|?]\s*\w|^\w)/gm;
app.human_text = app.human_text.replace(regex, function(m, p1) {
return p1.substring(0, p1.length - 1) + p1.substring(p1.length - 1).toUpperCase();
});
},
removeSpaceBeforeParagraph: function() {
var regex = /^[ ]+(\w)/gm;
app.human_text = app.human_text.replace(regex, function(m, p1) { return p1; });
},
addPunctuation: function() {
var regex = /([^?|!|\.|;|\s])$/gm;
if (app.punctuation.indexOf(app.human_text.charAt(app.human_text.length - 1)) < 0) {
app.human_text += settings.last_mark;
}
app.human_text = app.human_text.replace(regex, function(m, p1) { return p1 + '.'; });
},
addSpaceAfterPunctuation: function() {
var regex = /([^A-Z\u00C0-\u00DD]{1}[?|!|\.|;]+)([^ \n\.?!]{1})|([A-Z\u00C0-\u00DD][?|!|\.|;|,|:]+)([a-z\u00E1-\u00F6\u00F9-\u00FD]+)/g;
app.human_text = app.human_text.replace(regex, function(m, p1, p2, p3, p4) {
if (typeof p1 == 'undefined') {
p1 = p3;
p2 = p4;
}
return p1 + ' ' + p2;
});
},
trimAtEnd: function() {
app.human_text = app.human_text.trim();
},
toLowerCase: function() {
var regex1 = /(\b[a-z\u00E1-\u00F6\u00F9-\u00FD]{1}[A-Z\u00C0-\u00DD]{2,}\b)/g,
regex2 = /(\b[A-Z\u00C0-\u00DD]+[a-z\u00E1-\u00F6\u00F9-\u00FD]+[A-Z\u00C0-\u00DD]+[A-Z\u00C0-\u00DDa-z\u00E1-\u00F6\u00F9-\u00FD]*\b)/g,
regex3 = /(\b[a-z\u00E1-\u00F6\u00F9-\u00FD]+[A-Z\u00C0-\u00DD]+[a-z\u00E1-\u00F6\u00F9-\u00FD]+[a-z\u00E1-\u00F6\u00F9-\u00FDA-Z\u00C0-\u00DD]*\b)/g,
regex4 = /((?:\b[A-Z\u00C0-\u00DD]+\b[ ]+\b)+[A-Z\u00C0-\u00DD]+\b)/g;
app.human_text = app.human_text.replace(regex1, function(m, p1) { return p1.charAt(0).toUpperCase() + p1.slice(1).toLowerCase(); });
app.human_text = app.human_text.replace(regex2, function(m, p1) { return p1.toLowerCase(); });
app.human_text = app.human_text.replace(regex3, function(m, p1) { return p1.toLowerCase(); });
app.human_text = app.human_text.replace(regex4, function(m, p1) { return p1.toLowerCase(); });
},
applyText: function(el, event_type) {
var caret = 0, distance = 0;
if (event_type != 'keyup') {
el.val(app.human_text);
return;
}
caret = app.getCaret(el.get(0));
el.val(app.human_text);
if ( typeof caret == 'object' && typeof caret.end == 'number' ) {
distance = app.original_text.length - caret.end;
distance = app.human_text.length - distance;
app.moveCaret(el.get(0), distance);
}
},
getCaret: function(el) {
var start = 0, end = 0, normalizedValue, range,
textInputRange, len, endRange;
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else if (typeof document.selection != 'undefined') { // IE < 9
range = document.selection.createRange();
if (range && range.parentElement() == el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
},
moveCaret: function(input, distance) {
if (input.setSelectionRange) {
input.focus();
input.setSelectionRange(distance, distance);
} else if(input.createTextRange) {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd(distance);
range.moveStart(distance);
range.select();
}
}
};
this.filter('input, textarea').each(function () {
$(this).on('apply_human_text', function(event, event_type) {
var input = $(this);
app.original_text = input.val();
app.human_text = app.original_text;
// Return if empty
if (app.original_text == '') {
return;
}
if (event_type == 'change') {
// Remove space at end
app.trimAtEnd();
// If empty, apply the new empty text and finish
if (app.human_text == '') {
app.applyText(input, event_type);
return;
}
// Add a dot at end of each line (a question mark to the last one) if there is none.
app.addPunctuation();
// Add space after each punctuation ignoring A.B.R.E.V.I.A.T.I.O.N.S
app.addSpaceAfterPunctuation();
}
// Make string be lowercase if:
// Regex 1: A lone word is a wrong cAPITALIZED word (became Capitalized)
// Regex 2: A lone word is a wrong CApItalizeD/CApItalized word (became capitalized)
// Regex 3: A lone word is a wrong cApItAliZEd/cApItAliZED word (became capitalized)
// Regex 4: Two (or more) adjacent words are CAPITALIZED
app.toLowerCase();
// Make the first letter of each first word capitalized:
// In each start of line or when there's a punctuation before
app.ucFirstWord();
// Remove spaces in start of each line
app.removeSpaceBeforeParagraph();
// Return if nothing changed
if (app.original_text == app.human_text) { return; }
// Apply the new text
app.applyText(input, event_type);
});
$(this).on('keyup change', function(event) {
$(this).trigger('apply_human_text', event.type);
});
});
return this;
}
}(jQuery));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment