@qooxdoo/framework
Version:
The JS Framework for Coders
141 lines (114 loc) • 4.51 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Sebastian Werner (wpbasti)
* Adrian Olaru (adrianolaru)
======================================================================
This class contains code based on the following work:
* Cross-Browser Split
http://blog.stevenlevithan.com/archives/cross-browser-split
Version 1.0.1
Copyright:
(c) 2006-2007, Steven Levithan <http://stevenlevithan.com>
License:
MIT: http://www.opensource.org/licenses/mit-license.php
Authors:
* Steven Levithan
************************************************************************ */
/**
* Implements an ECMA-compliant, uniform cross-browser split method
*/
qx.Bootstrap.define("qx.util.StringSplit",
{
statics :
{
/**
* ECMA-compliant, uniform cross-browser split method
*
* @param str {String} Incoming string to split
* @param separator {RegExp} Specifies the character to use for separating the string.
* The separator is treated as a string or a regular expression. If separator is
* omitted, the array returned contains one element consisting of the entire string.
* @param limit {Integer?} Integer specifying a limit on the number of splits to be found.
* @return {String[]} split string
*/
split : function (str, separator, limit)
{
// if `separator` is not a regex, use the native `split`
if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
return String.prototype.split.call(str, separator, limit);
}
var output = [],
lastLastIndex = 0,
flags = (separator.ignoreCase ? "i" : "") +
(separator.multiline ? "m" : "") +
(separator.sticky ? "y" : ""),
separator = RegExp(separator.source, flags + "g"), // make `global` and avoid `lastIndex` issues by working with a copy
separator2, match, lastIndex, lastLength,
compliantExecNpcg = /()??/.exec("")[1] === undefined; // NPCG: nonparticipating capturing group
str = str + ""; // type conversion
if (!compliantExecNpcg) {
separator2 = RegExp("^" + separator.source + "$(?!\\s)", flags); // doesn't need /g or /y, but they don't hurt
}
/* behavior for `limit`: if it's...
- `undefined`: no limit.
- `NaN` or zero: return an empty array.
- a positive number: use `Math.floor(limit)`.
- a negative number: no limit.
- other: type-convert, then use the above rules. */
if (limit === undefined || +limit < 0) {
limit = Infinity;
} else {
limit = Math.floor(+limit);
if (!limit) {
return [];
}
}
while (match = separator.exec(str))
{
lastIndex = match.index + match[0].length; // `separator.lastIndex` is not reliable cross-browser
if (lastIndex > lastLastIndex) {
output.push(str.slice(lastLastIndex, match.index));
// fix browsers whose `exec` methods don't consistently return `undefined` for nonparticipating capturing groups
if (!compliantExecNpcg && match.length > 1)
{
match[0].replace(separator2, function () {
for (var i = 1; i < arguments.length - 2; i++)
{
if (arguments[i] === undefined) {
match[i] = undefined;
}
}
});
}
if (match.length > 1 && match.index < str.length) {
Array.prototype.push.apply(output, match.slice(1));
}
lastLength = match[0].length;
lastLastIndex = lastIndex;
if (output.length >= limit) {
break;
}
}
if (separator.lastIndex === match.index) {
separator.lastIndex++; // avoid an infinite loop
}
}
if (lastLastIndex === str.length)
{
if (lastLength || !separator.test("")) {
output.push("");
}
} else {
output.push(str.slice(lastLastIndex));
}
return output.length > limit ? output.slice(0, limit) : output;
}
}
});