|
|
|
|
@ -62,7 +62,7 @@
|
|
|
|
|
* @return a two-dimensional array containing the data, with the first row containing headers
|
|
|
|
|
**/
|
|
|
|
|
function ImportJSON(url, query, parseOptions) {
|
|
|
|
|
return ImportJSONAdvanced(url, null, query, parseOptions, includeXPath_, defaultTransform_);
|
|
|
|
|
return ImportJSONAdvanced(url, null, query, parseOptions, includeXPath_, defaultTransform_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -105,26 +105,26 @@ function ImportJSON(url, query, parseOptions) {
|
|
|
|
|
* @return a two-dimensional array containing the data, with the first row containing headers
|
|
|
|
|
**/
|
|
|
|
|
function ImportJSONViaPost(url, payload, fetchOptions, query, parseOptions) {
|
|
|
|
|
var postOptions = parseToObject_(fetchOptions);
|
|
|
|
|
var postOptions = parseToObject_(fetchOptions);
|
|
|
|
|
|
|
|
|
|
if (postOptions["method"] == null) {
|
|
|
|
|
postOptions["method"] = "POST";
|
|
|
|
|
}
|
|
|
|
|
if (postOptions["method"] == null) {
|
|
|
|
|
postOptions["method"] = "POST";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (postOptions["payload"] == null) {
|
|
|
|
|
postOptions["payload"] = payload;
|
|
|
|
|
}
|
|
|
|
|
if (postOptions["payload"] == null) {
|
|
|
|
|
postOptions["payload"] = payload;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (postOptions["contentType"] == null) {
|
|
|
|
|
postOptions["contentType"] = "application/x-www-form-urlencoded";
|
|
|
|
|
}
|
|
|
|
|
if (postOptions["contentType"] == null) {
|
|
|
|
|
postOptions["contentType"] = "application/x-www-form-urlencoded";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
convertToBool_(postOptions, "validateHttpsCertificates");
|
|
|
|
|
convertToBool_(postOptions, "useIntranet");
|
|
|
|
|
convertToBool_(postOptions, "followRedirects");
|
|
|
|
|
convertToBool_(postOptions, "muteHttpExceptions");
|
|
|
|
|
convertToBool_(postOptions, "validateHttpsCertificates");
|
|
|
|
|
convertToBool_(postOptions, "useIntranet");
|
|
|
|
|
convertToBool_(postOptions, "followRedirects");
|
|
|
|
|
convertToBool_(postOptions, "muteHttpExceptions");
|
|
|
|
|
|
|
|
|
|
return ImportJSONAdvanced(url, postOptions, query, parseOptions, includeXPath_, defaultTransform_);
|
|
|
|
|
return ImportJSONAdvanced(url, postOptions, query, parseOptions, includeXPath_, defaultTransform_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -167,10 +167,10 @@ function ImportJSONViaPost(url, payload, fetchOptions, query, parseOptions) {
|
|
|
|
|
* @return a two-dimensional array containing the data, with the first row containing headers
|
|
|
|
|
**/
|
|
|
|
|
function ImportJSONAdvanced(url, fetchOptions, query, parseOptions, includeFunc, transformFunc) {
|
|
|
|
|
var jsondata = UrlFetchApp.fetch(url, fetchOptions);
|
|
|
|
|
var object = JSON.parse(jsondata.getContentText());
|
|
|
|
|
var jsondata = UrlFetchApp.fetch(url, fetchOptions);
|
|
|
|
|
var object = JSON.parse(jsondata.getContentText());
|
|
|
|
|
|
|
|
|
|
return parseJSONObject_(object, query, parseOptions, includeFunc, transformFunc);
|
|
|
|
|
return parseJSONObject_(object, query, parseOptions, includeFunc, transformFunc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -181,7 +181,7 @@ function ImportJSONAdvanced(url, fetchOptions, query, parseOptions, includeFunc,
|
|
|
|
|
* @return the value encoded using URL percent-encoding
|
|
|
|
|
*/
|
|
|
|
|
function URLEncode(value) {
|
|
|
|
|
return encodeURIComponent(value.toString());
|
|
|
|
|
return encodeURIComponent(value.toString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -207,57 +207,59 @@ function URLEncode(value) {
|
|
|
|
|
* I received an error that the "oAuthServiceName" was not a valid value. [twl 18.Apr.13]
|
|
|
|
|
*/
|
|
|
|
|
function AddOAuthService__(name, accessTokenUrl, requestTokenUrl, authorizationUrl, consumerKey, consumerSecret, method, paramLocation) {
|
|
|
|
|
var oAuthConfig = UrlFetchApp.addOAuthService(name);
|
|
|
|
|
var oAuthConfig = UrlFetchApp.addOAuthService(name);
|
|
|
|
|
|
|
|
|
|
if (accessTokenUrl != null && accessTokenUrl.length > 0) {
|
|
|
|
|
oAuthConfig.setAccessTokenUrl(accessTokenUrl);
|
|
|
|
|
}
|
|
|
|
|
if (accessTokenUrl != null && accessTokenUrl.length > 0) {
|
|
|
|
|
oAuthConfig.setAccessTokenUrl(accessTokenUrl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (requestTokenUrl != null && requestTokenUrl.length > 0) {
|
|
|
|
|
oAuthConfig.setRequestTokenUrl(requestTokenUrl);
|
|
|
|
|
}
|
|
|
|
|
if (requestTokenUrl != null && requestTokenUrl.length > 0) {
|
|
|
|
|
oAuthConfig.setRequestTokenUrl(requestTokenUrl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (authorizationUrl != null && authorizationUrl.length > 0) {
|
|
|
|
|
oAuthConfig.setAuthorizationUrl(authorizationUrl);
|
|
|
|
|
}
|
|
|
|
|
if (authorizationUrl != null && authorizationUrl.length > 0) {
|
|
|
|
|
oAuthConfig.setAuthorizationUrl(authorizationUrl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (consumerKey != null && consumerKey.length > 0) {
|
|
|
|
|
oAuthConfig.setConsumerKey(consumerKey);
|
|
|
|
|
}
|
|
|
|
|
if (consumerKey != null && consumerKey.length > 0) {
|
|
|
|
|
oAuthConfig.setConsumerKey(consumerKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (consumerSecret != null && consumerSecret.length > 0) {
|
|
|
|
|
oAuthConfig.setConsumerSecret(consumerSecret);
|
|
|
|
|
}
|
|
|
|
|
if (consumerSecret != null && consumerSecret.length > 0) {
|
|
|
|
|
oAuthConfig.setConsumerSecret(consumerSecret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (method != null && method.length > 0) {
|
|
|
|
|
oAuthConfig.setMethod(method);
|
|
|
|
|
}
|
|
|
|
|
if (method != null && method.length > 0) {
|
|
|
|
|
oAuthConfig.setMethod(method);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (paramLocation != null && paramLocation.length > 0) {
|
|
|
|
|
oAuthConfig.setParamLocation(paramLocation);
|
|
|
|
|
}
|
|
|
|
|
if (paramLocation != null && paramLocation.length > 0) {
|
|
|
|
|
oAuthConfig.setParamLocation(paramLocation);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses a JSON object and returns a two-dimensional array containing the data of that object.
|
|
|
|
|
*/
|
|
|
|
|
function parseJSONObject_(object, query, options, includeFunc, transformFunc) {
|
|
|
|
|
var headers = new Array();
|
|
|
|
|
var data = new Array();
|
|
|
|
|
var headers = new Array();
|
|
|
|
|
var data = new Array();
|
|
|
|
|
|
|
|
|
|
if (query && !Array.isArray(query) && query.toString().indexOf(",") != -1) {
|
|
|
|
|
query = query.toString().split(",");
|
|
|
|
|
}
|
|
|
|
|
if (query && !Array.isArray(query) && query.toString().indexOf(",") != -1) {
|
|
|
|
|
query = query.toString().split(",");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options) {
|
|
|
|
|
options = options.toString().split(",");
|
|
|
|
|
}
|
|
|
|
|
if (options) {
|
|
|
|
|
options = options.toString().split(",");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parseData_(headers, data, "", {rowIndex: 1}, object, query, options, includeFunc);
|
|
|
|
|
parseHeaders_(headers, data);
|
|
|
|
|
transformData_(data, options, transformFunc);
|
|
|
|
|
parseData_(headers, data, "", {
|
|
|
|
|
rowIndex: 1
|
|
|
|
|
}, object, query, options, includeFunc);
|
|
|
|
|
parseHeaders_(headers, data);
|
|
|
|
|
transformData_(data, options, transformFunc);
|
|
|
|
|
|
|
|
|
|
return hasOption_(options, "noHeaders") ? (data.length > 1 ? data.slice(1) : new Array()) : data;
|
|
|
|
|
return hasOption_(options, "noHeaders") ? (data.length > 1 ? data.slice(1) : new Array()) : data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -278,114 +280,114 @@ function parseJSONObject_(object, query, options, includeFunc, transformFunc) {
|
|
|
|
|
* If the value is a scalar, the value is inserted directly into the data array.
|
|
|
|
|
*/
|
|
|
|
|
function parseData_(headers, data, path, state, value, query, options, includeFunc) {
|
|
|
|
|
var dataInserted = false;
|
|
|
|
|
var dataInserted = false;
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(value) && isObjectArray_(value)) {
|
|
|
|
|
for (var i = 0; i < value.length; i++) {
|
|
|
|
|
if (parseData_(headers, data, path, state, value[i], query, options, includeFunc)) {
|
|
|
|
|
dataInserted = true;
|
|
|
|
|
if (Array.isArray(value) && isObjectArray_(value)) {
|
|
|
|
|
for (var i = 0; i < value.length; i++) {
|
|
|
|
|
if (parseData_(headers, data, path, state, value[i], query, options, includeFunc)) {
|
|
|
|
|
dataInserted = true;
|
|
|
|
|
|
|
|
|
|
if (data[state.rowIndex]) {
|
|
|
|
|
state.rowIndex++;
|
|
|
|
|
if (data[state.rowIndex]) {
|
|
|
|
|
state.rowIndex++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (isObject_(value)) {
|
|
|
|
|
for (key in value) {
|
|
|
|
|
if (parseData_(headers, data, path + "/" + key, state, value[key], query, options, includeFunc)) {
|
|
|
|
|
} else if (isObject_(value)) {
|
|
|
|
|
for (key in value) {
|
|
|
|
|
if (parseData_(headers, data, path + "/" + key, state, value[key], query, options, includeFunc)) {
|
|
|
|
|
dataInserted = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (!includeFunc || includeFunc(query, path, options)) {
|
|
|
|
|
// Handle arrays containing only scalar values
|
|
|
|
|
if (Array.isArray(value)) {
|
|
|
|
|
value = value.join();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Insert new row if one doesn't already exist
|
|
|
|
|
if (!data[state.rowIndex]) {
|
|
|
|
|
data[state.rowIndex] = new Array();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add a new header if one doesn't exist
|
|
|
|
|
if (!headers[path] && headers[path] != 0) {
|
|
|
|
|
headers[path] = Object.keys(headers).length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Insert the data
|
|
|
|
|
data[state.rowIndex][headers[path]] = value;
|
|
|
|
|
dataInserted = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (!includeFunc || includeFunc(query, path, options)) {
|
|
|
|
|
// Handle arrays containing only scalar values
|
|
|
|
|
if (Array.isArray(value)) {
|
|
|
|
|
value = value.join();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Insert new row if one doesn't already exist
|
|
|
|
|
if (!data[state.rowIndex]) {
|
|
|
|
|
data[state.rowIndex] = new Array();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add a new header if one doesn't exist
|
|
|
|
|
if (!headers[path] && headers[path] != 0) {
|
|
|
|
|
headers[path] = Object.keys(headers).length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Insert the data
|
|
|
|
|
data[state.rowIndex][headers[path]] = value;
|
|
|
|
|
dataInserted = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dataInserted;
|
|
|
|
|
return dataInserted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses the headers array and inserts it into the first row of the data array.
|
|
|
|
|
*/
|
|
|
|
|
function parseHeaders_(headers, data) {
|
|
|
|
|
data[0] = new Array();
|
|
|
|
|
data[0] = new Array();
|
|
|
|
|
|
|
|
|
|
for (key in headers) {
|
|
|
|
|
data[0][headers[key]] = key;
|
|
|
|
|
}
|
|
|
|
|
for (key in headers) {
|
|
|
|
|
data[0][headers[key]] = key;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Applies the transform function for each element in the data array, going through each column of each row.
|
|
|
|
|
*/
|
|
|
|
|
function transformData_(data, options, transformFunc) {
|
|
|
|
|
for (var i = 0; i < data.length; i++) {
|
|
|
|
|
for (var j = 0; j < data[i].length; j++) {
|
|
|
|
|
transformFunc(data, i, j, options);
|
|
|
|
|
for (var i = 0; i < data.length; i++) {
|
|
|
|
|
for (var j = 0; j < data[i].length; j++) {
|
|
|
|
|
transformFunc(data, i, j, options);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if the given test value is an object; false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
function isObject_(test) {
|
|
|
|
|
return Object.prototype.toString.call(test) === '[object Object]';
|
|
|
|
|
return Object.prototype.toString.call(test) === '[object Object]';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if the given test value is an array containing at least one object; false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
function isObjectArray_(test) {
|
|
|
|
|
for (var i = 0; i < test.length; i++) {
|
|
|
|
|
if (isObject_(test[i])) {
|
|
|
|
|
return true;
|
|
|
|
|
for (var i = 0; i < test.length; i++) {
|
|
|
|
|
if (isObject_(test[i])) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if the given query applies to the given path.
|
|
|
|
|
*/
|
|
|
|
|
function includeXPath_(query, path, options) {
|
|
|
|
|
if (!query) {
|
|
|
|
|
return true;
|
|
|
|
|
} else if (Array.isArray(query)) {
|
|
|
|
|
for (var i = 0; i < query.length; i++) {
|
|
|
|
|
if (applyXPathRule_(query[i], path, options)) {
|
|
|
|
|
if (!query) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} else if (Array.isArray(query)) {
|
|
|
|
|
for (var i = 0; i < query.length; i++) {
|
|
|
|
|
if (applyXPathRule_(query[i], path, options)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return applyXPathRule_(query, path, options);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return applyXPathRule_(query, path, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if the rule applies to the given path.
|
|
|
|
|
*/
|
|
|
|
|
function applyXPathRule_(rule, path, options) {
|
|
|
|
|
return path.indexOf(rule) == 0;
|
|
|
|
|
return path.indexOf(rule) == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -395,7 +397,7 @@ function applyXPathRule_(rule, path, options) {
|
|
|
|
|
* of the rows representing their parent elements.
|
|
|
|
|
* - Values longer than 256 characters get truncated.
|
|
|
|
|
* - Values in row 0 (headers) have slashes converted to spaces, common prefixes removed and the resulting text converted to title
|
|
|
|
|
* case.
|
|
|
|
|
* case.
|
|
|
|
|
*
|
|
|
|
|
* To change this behavior, pass in one of these values in the options parameter:
|
|
|
|
|
*
|
|
|
|
|
@ -405,69 +407,69 @@ function applyXPathRule_(rule, path, options) {
|
|
|
|
|
* debugLocation: Prepend each value with the row & column it belongs in
|
|
|
|
|
*/
|
|
|
|
|
function defaultTransform_(data, row, column, options) {
|
|
|
|
|
if (!data[row][column]) {
|
|
|
|
|
if (row < 2 || hasOption_(options, "noInherit")) {
|
|
|
|
|
data[row][column] = "";
|
|
|
|
|
} else {
|
|
|
|
|
data[row][column] = data[row-1][column];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasOption_(options, "rawHeaders") && row == 0) {
|
|
|
|
|
if (column == 0 && data[row].length > 1) {
|
|
|
|
|
removeCommonPrefixes_(data, row);
|
|
|
|
|
if (!data[row][column]) {
|
|
|
|
|
if (row < 2 || hasOption_(options, "noInherit")) {
|
|
|
|
|
data[row][column] = "";
|
|
|
|
|
} else {
|
|
|
|
|
data[row][column] = data[row - 1][column];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data[row][column] = toTitleCase_(data[row][column].toString().replace(/[\/\_]/g, ""));
|
|
|
|
|
} else if (hasOption_(options, "rawHeaders") && row == 0) {
|
|
|
|
|
data[row][column] = data[row][column].toString().replace(/[\/\_]/g, "");
|
|
|
|
|
}
|
|
|
|
|
if (!hasOption_(options, "rawHeaders") && row == 0) {
|
|
|
|
|
if (column == 0 && data[row].length > 1) {
|
|
|
|
|
removeCommonPrefixes_(data, row);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasOption_(options, "noTruncate") && data[row][column]) {
|
|
|
|
|
data[row][column] = data[row][column].toString().substr(0, 256);
|
|
|
|
|
}
|
|
|
|
|
data[row][column] = toTitleCase_(data[row][column].toString().replace(/[\/\_]/g, ""));
|
|
|
|
|
} else if (hasOption_(options, "rawHeaders") && row == 0) {
|
|
|
|
|
data[row][column] = data[row][column].toString().replace(/[\/\_]/g, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hasOption_(options, "debugLocation")) {
|
|
|
|
|
data[row][column] = "[" + row + "," + column + "]" + data[row][column];
|
|
|
|
|
}
|
|
|
|
|
if (!hasOption_(options, "noTruncate") && data[row][column]) {
|
|
|
|
|
data[row][column] = data[row][column].toString().substr(0, 256);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hasOption_(options, "debugLocation")) {
|
|
|
|
|
data[row][column] = "[" + row + "," + column + "]" + data[row][column];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If all the values in the given row share the same prefix, remove that prefix.
|
|
|
|
|
*/
|
|
|
|
|
function removeCommonPrefixes_(data, row) {
|
|
|
|
|
var matchIndex = data[row][0].length;
|
|
|
|
|
var matchIndex = data[row][0].length;
|
|
|
|
|
|
|
|
|
|
for (var i = 1; i < data[row].length; i++) {
|
|
|
|
|
matchIndex = findEqualityEndpoint_(data[row][i-1], data[row][i], matchIndex);
|
|
|
|
|
for (var i = 1; i < data[row].length; i++) {
|
|
|
|
|
matchIndex = findEqualityEndpoint_(data[row][i - 1], data[row][i], matchIndex);
|
|
|
|
|
|
|
|
|
|
if (matchIndex == 0) {
|
|
|
|
|
return;
|
|
|
|
|
if (matchIndex == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < data[row].length; i++) {
|
|
|
|
|
data[row][i] = data[row][i].substring(matchIndex, data[row][i].length);
|
|
|
|
|
}
|
|
|
|
|
for (var i = 0; i < data[row].length; i++) {
|
|
|
|
|
data[row][i] = data[row][i].substring(matchIndex, data[row][i].length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Locates the index where the two strings values stop being equal, stopping automatically at the stopAt index.
|
|
|
|
|
*/
|
|
|
|
|
function findEqualityEndpoint_(string1, string2, stopAt) {
|
|
|
|
|
if (!string1 || !string2) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var maxEndpoint = Math.min(stopAt, string1.length, string2.length);
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < maxEndpoint; i++) {
|
|
|
|
|
if (string1.charAt(i) != string2.charAt(i)) {
|
|
|
|
|
return i;
|
|
|
|
|
if (!string1 || !string2) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return maxEndpoint;
|
|
|
|
|
var maxEndpoint = Math.min(stopAt, string1.length, string2.length);
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < maxEndpoint; i++) {
|
|
|
|
|
if (string1.charAt(i) != string2.charAt(i)) {
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return maxEndpoint;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -475,57 +477,59 @@ function findEqualityEndpoint_(string1, string2, stopAt) {
|
|
|
|
|
* Converts the text to title case.
|
|
|
|
|
*/
|
|
|
|
|
function toTitleCase_(text) {
|
|
|
|
|
if (text == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
if (text == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return text.replace(/\w\S*/g, function(word) { return word.charAt(0).toUpperCase() + word.substr(1).toLowerCase(); });
|
|
|
|
|
return text.replace(/\w\S*/g, function(word) {
|
|
|
|
|
return word.charAt(0).toUpperCase() + word.substr(1).toLowerCase();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if the given set of options contains the given option.
|
|
|
|
|
*/
|
|
|
|
|
function hasOption_(options, option) {
|
|
|
|
|
return options && options.indexOf(option) >= 0;
|
|
|
|
|
return options && options.indexOf(option) >= 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses the given string into an object, trimming any leading or trailing spaces from the keys.
|
|
|
|
|
*/
|
|
|
|
|
function parseToObject_(text) {
|
|
|
|
|
var map = new Object();
|
|
|
|
|
var entries = (text != null && text.trim().length > 0) ? text.toString().split(",") : new Array();
|
|
|
|
|
var map = new Object();
|
|
|
|
|
var entries = (text != null && text.trim().length > 0) ? text.toString().split(",") : new Array();
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
|
|
|
addToMap_(map, entries[i]);
|
|
|
|
|
}
|
|
|
|
|
for (var i = 0; i < entries.length; i++) {
|
|
|
|
|
addToMap_(map, entries[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return map;
|
|
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses the given entry and adds it to the given map, trimming any leading or trailing spaces from the key.
|
|
|
|
|
*/
|
|
|
|
|
function addToMap_(map, entry) {
|
|
|
|
|
var equalsIndex = entry.indexOf("=");
|
|
|
|
|
var key = (equalsIndex != -1) ? entry.substring(0, equalsIndex) : entry;
|
|
|
|
|
var value = (key.length + 1 < entry.length) ? entry.substring(key.length + 1) : "";
|
|
|
|
|
var equalsIndex = entry.indexOf("=");
|
|
|
|
|
var key = (equalsIndex != -1) ? entry.substring(0, equalsIndex) : entry;
|
|
|
|
|
var value = (key.length + 1 < entry.length) ? entry.substring(key.length + 1) : "";
|
|
|
|
|
|
|
|
|
|
map[key.trim()] = value;
|
|
|
|
|
map[key.trim()] = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the given value as a boolean.
|
|
|
|
|
*/
|
|
|
|
|
function toBool_(value) {
|
|
|
|
|
return value == null ? false : (value.toString().toLowerCase() == "true" ? true : false);
|
|
|
|
|
return value == null ? false : (value.toString().toLowerCase() == "true" ? true : false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Converts the value for the given key in the given map to a bool.
|
|
|
|
|
*/
|
|
|
|
|
function convertToBool_(map, key) {
|
|
|
|
|
if (map[key] != null) {
|
|
|
|
|
map[key] = toBool_(map[key]);
|
|
|
|
|
}
|
|
|
|
|
if (map[key] != null) {
|
|
|
|
|
map[key] = toBool_(map[key]);
|
|
|
|
|
}
|
|
|
|
|
}
|