string-direction
Version:
String Direction is a JavaScript library for detection of direction of `String` objects in JavaScript.
150 lines (119 loc) • 4.25 kB
JavaScript
(function(){
var LTR_MARK = "\u200e",
RTL_MARK = "\u200f",
LTR = 'ltr', // Left to right direction content
RTL = 'rtl', // Right to left direction content
BIDI = 'bidi', // Both directions - any and all directions will not be ok
NODI = ''; // No direction - any and all directions are ok
var rtlSciriptRanges = {
Hebrew: ["0590","05FF"],
Arabic: ["0600","06FF"],
NKo: ["07C0","07FF"],
Syriac: ["0700","074F"],
Thaana: ["0780","07BF"],
Tifinagh: ["2D30","2D7F"]
};
/*
* Gets string direction
* @param {string} - String to check for direction
* @returns {string} - 'ltr' if given string is left-to-right,
* 'rtl' if it's right-to-left and 'bidi' if it has both types of characters
*/
function getDirection(string) {
if(typeof string === 'undefined')
throw new Error('TypeError missing argument');
if(typeof string !== 'string')
throw new Error('TypeError getDirection expects strings');
if(string === '')
return NODI;
if(string.indexOf(LTR_MARK) > -1 && string.indexOf(RTL_MARK) > -1)
return BIDI;
if(string.indexOf(LTR_MARK) > -1)
return LTR;
if(string.indexOf(RTL_MARK) > -1)
return RTL;
var hasRtl = hasDirectionCharacters(string, RTL);
var hasLtr = hasDirectionCharacters(string, LTR);
if(hasRtl && hasLtr)
return BIDI;
if(hasLtr)
return LTR;
if(hasRtl)
return RTL;
return NODI;
}
/**
* Determine if a string has characters in right-to-left or left-to-right Unicode blocks
* @param {string} string - String to check for characters
* @param {string} direction - Direction to check. Either 'ltr' or 'rtl' string
* @returns {boolean} - True if given string has direction specific characters, False otherwise
*/
function hasDirectionCharacters(string, direction) {
var i, char, range, charIsRtl,
hasRtl = false,
hasLtr = false,
hasDigit = false;
hasDigit = (string.search(/[0-9]/) > -1);
// Remove white space and non directional characters
string = string.replace(/[\s\n\0\f\t\v\'\"\-0-9\+\?\!]+/gm, '');
// Loop through each character
for(i=0; i<string.length; i++) {
char = string.charAt(i);
// Assume character is not rtl
charIsRtl = false;
// Test each character against all ltr script ranges
for (range in rtlSciriptRanges) {
if (rtlSciriptRanges.hasOwnProperty(range)) {
if ( isInScriptRange( char,
rtlSciriptRanges[range][0],
rtlSciriptRanges[range][1]) ){
// If character is rtl, set rtl flag (hasRtl) for string to true
hasRtl = true;
// Set rtl flag for this character to true
charIsRtl = true;
}
}
}
// If this character is *not* rtl then it is ltr and string has
// ltr characters
if(charIsRtl === false) {
hasLtr = true;
}
}
if(direction === RTL)
return hasRtl;
if(direction === LTR)
return hasLtr || (!hasRtl && hasDigit);
}
/**
* Checks if a a character is in a Unicode block range
* @param {string} char - The character to check. An string with only one character
* @param {string} from - Starting Unicode code of block in hexadecimal. Example: "2D30"
* @param {string} to - Ending Unicode code of block in hexadecimal. Example: "2F30"
* @returns {boolean} - true if char is in range.
*/
function isInScriptRange(char, from, to) {
var charCode = char.charCodeAt(0),
fromCode = parseInt(from, 16),
toCode = parseInt(to, 16);
return charCode > fromCode && charCode < toCode;
}
/**
* Monkey-patch String global object to expose getDirection method
*/
function patchStringPrototype () {
String.prototype.getDirection = function() {
return getDirection(this.valueOf());
};
}
// TODO make it AMD friendly
if(typeof exports !== 'undefined') {
exports.getDirection = getDirection;
exports.patch = patchStringPrototype;
} else {
this.stringDirection = {
getDirection: getDirection,
patch: patchStringPrototype
};
}
}).call(this);