/*************************************************************************
*
* ADOBE CONFIDENTIAL
* ___________________
*
* Copyright 2012 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
*
**************************************************************************/
/**
* A static JavaScript object that defines a number of utility methods and convenience
* functions for string and date formatting and parsing.
*
* @class util
*/
function util() { };
/**
* Formats one or more arguments as a string according to a format string. It is similar
* to the C function of the same name.
*
* @method printf
* @param cFormat {String} The format string to use.
* @param [arguments] {Any} The optional arguments(s) that contain the data to be inserted
* in place of the % tags specified in the first parameter, the format string. The number of
* optional arguments must be the same as the number of % tags.
* @return {String} A result string formatted as specified.
*/
util.printf = function()
{
var ret = "";
try
{
// limit number of argument to less than 50 for now
if (arguments.length < 50)
{
ret = sprintf.apply(this, arguments);
}
}
catch(e) {}
return ret;
};
/**
* Returns a date using a specified format.
*
* @method printd
* @param cFormat {String} A string that is a pattern of supported substrings that are place-holders
* for date and time data.
* @param oDate {Object} A Date object to format.
* @return {String} The formatted date string.
*/
util.printd = function()
{
var formattedDate = "";
if (validateInput.apply(this, arguments))
{
var cFormat = arguments[0].toString();
var date = arguments[1];
if ((cFormat.length == 1) && isNumber(cFormat.charAt(0)))
{
// Note: All the cases below behave different from what is specified in Acrobat JS Reference
// but they are in sync with the behaviour on desktop Acrobat
switch (cFormat.charAt(0))
{
case "0":
formattedDate = util.printd("D:yyyymmddHHMMss", date);
break;
case "1":
formattedDate = util.printd("yyyy.mm.dd HH:MM:ss", date);
break;
case "2":
formattedDate = util.printd("m/d/yy h:MM:ss tt", date);
break;
}
}
else
{
var pattern = /m+|d+|y+|H+|h+|M+|s+|t+|j+|\\./g;
var matches = cFormat.match(pattern);
if (matches)
{
formattedDate += cFormat.substring(0, search(cFormat, matches[0]));
for (var i = 0; i < matches.length; i++)
{
var count = matches[i].length;
formattedDate += getFormattedComponentValue(date, matches[i]);
if ((i + 1) < matches.length)
{
var separatorBeginIndex = search(cFormat, matches[i]) + count;
var separatorEndIndex = search(cFormat.slice(separatorBeginIndex), matches[i+1]) + separatorBeginIndex;
formattedDate += cFormat.substring(separatorBeginIndex, separatorEndIndex);
cFormat = cFormat.slice(separatorEndIndex);
}
else
{
var separatorBeginIndex = search(cFormat, matches[i]) + count;
formattedDate += cFormat.slice(separatorBeginIndex);
}
}
}
else
{
formattedDate = cFormat;
}
}
}
return formattedDate;
/**
* Returns formatted date component.
*
* @private
* @method getFormattedComponentValue
* @param date {Object} The date object.
* @param match {String} The component match found in the format string.
* @return {String} Formatted date component.
*/
function getFormattedComponentValue(date, match)
{
var component = match.charAt(0);
var count = match.length;
var formattedComponentValue = "";
switch (component)
{
case "m":
if (count == 1)
{
formattedComponentValue = (date.getMonth() + 1).toString();
}
else if (count == 2)
{
formattedComponentValue = lpad(date.getMonth() + 1, 2);
}
else if (count == 3)
{
formattedComponentValue = getMonthString((date.getMonth() + 1), true);
}
else if (count == 4)
{
formattedComponentValue = getMonthString((date.getMonth() + 1), false);
}
break;
case "d":
if (count == 1)
{
formattedComponentValue = date.getDate().toString();
}
else if (count == 2)
{
formattedComponentValue = lpad(date.getDate(), 2);
}
else if (count == 3)
{
formattedComponentValue = getDayString((date.getDay() + 1), true);
}
else if (count == 4)
{
formattedComponentValue = getDayString((date.getDay() + 1), false);
}
break;
case "y":
if (count == 2)
{
var year = lpad(date.getFullYear(), 4);
formattedComponentValue = year.charAt(2) + year.charAt(3);
}
else if (count == 4)
{
formattedComponentValue = lpad(date.getFullYear(), 4);
}
break;
case "H":
if (count == 1)
{
formattedComponentValue = date.getHours().toString();
}
else if (count == 2)
{
formattedComponentValue = lpad(date.getHours(), 2);
}
break;
case "h":
var hours = date.getHours() % 12; // converting to 12 hour format
if (hours == 0)
hours = 12;
if (count == 1)
{
formattedComponentValue = hours.toString();
}
else if (count == 2)
{
formattedComponentValue = lpad(hours, 2);
}
break;
case "M":
if (count == 1)
{
formattedComponentValue = date.getMinutes().toString();
}
else if (count == 2)
{
formattedComponentValue = lpad(date.getMinutes(), 2);
}
break;
case "s":
if (count == 1)
{
formattedComponentValue = date.getSeconds().toString();
}
else if (count == 2)
{
formattedComponentValue = lpad(date.getSeconds(), 2);
}
break;
case "t":
var tValue = "";
if (date.getHours() < 12)
tValue = EScriptString.get("IDS_AM");
else
tValue = EScriptString.get("IDS_PM");
if (count == 1)
{
formattedComponentValue = tValue.chatAt(0);
}
else if (count == 2)
{
formattedComponentValue = tValue;
}
break;
case "\\":
formattedComponentValue = match[1];
break;
}
return formattedComponentValue;
}
/**
* Returns the day string for the given index.
*
* @private
* @method getDayString
* @param index {Number} The index of the day. For e.g. 1 for Sunday.
* @param abbreviated {Boolean} Specifies if the abbreviated string is to be returned or the entire string.
* @return {String} The day string for the index.
*/
function getDayString(index, abbreviated)
{
// returns the string (abbreviated or full) corresponding to the given day or a string that
// is indicative of the fact that the index was invalid
var IDS_DAY_INFO = EScriptString.get("IDS_DAY_INFO");
var IDS_INVALID_MONTH = EScriptString.get("IDS_INVALID_MONTH");
var result = "";
var datre = new RegExp("(\\w+)\\[" + index + "\\]", "g");
var matches = IDS_DAY_INFO.match(monthre);
if (matches.length == 2)
{
if (abbreviated)
result = matches[1].slice(0, (matches[1].indexOf("[")));
else
result = matches[0].slice(0, (matches[1].indexOf("[")));
return result;
}
return IDS_INVALID_MONTH;
}
/**
* Returns the month string for the given index.
*
* @private
* @method getMonthString
* @param index {Number} The index of the day. For e.g. 1 for January.
* @param abbreviated {Boolean} Specifies if the abbreviated string is to be returned or the entire string.
* @return {String} The month string for the index.
*/
function getMonthString(index, abbreviated)
{
// returns the string (abbreviated or full) corresponding to the given month or a string that
// is indicative of the fact that the index was invalid
// TODO_READER_MOBILE<pvyas>: modify the IDS_MONTH_INFO string so that it includes abbreviated May.
// this will prevent special handling, and then getDateString and getMonthString can share code.
if (abbreviated)
{
var IDS_MONTH_INFO = EScriptString.get("IDS_MONTH_INFO");
var IDS_INVALID_MONTH = EScriptString.get("IDS_INVALID_MONTH");
var monthre = new RegExp("(\\w+)\\[" + index + "\\]", "g");
var matches = IDS_MONTH_INFO.match(monthre);
if (matches.length == 2)
return matches[1].slice(0, (matches[1].indexOf("[")));
return AFGetMonthString(index); // if 2 matches are not found we try and default to full name
}
else
{
return AFGetMonthString(index);
}
}
/**
* Does input validation for printd method.
*
* @private
* @method validateInput
* @return {Boolean} True if input is valid, otherwise false.
*/
function validateInput()
{
var result = true;
// check if number of arguments are valid
if (!((arguments.length > 1) && (arguments.length < 4)))
{
result = false;
}
else
{
// check if argument 1 is valid
if (!((typeof(arguments[0]) == "string") || (typeof(arguments[0]) == "number")))
{
result = false;
}
else
{
if (typeof(arguments[0]) == "number")
{
if (!((arguments[0] >= 0) && (arguments[0] <= 2)))
result = false;
}
}
// check if argument 2 is valid
if (!(arguments[1] instanceof Date))
{
result = false;
}
}
return result;
}
};
/**
* Formats a source string, cSource, according to a formatting string, cFormat.
*
* @method printx
* @param cFormat {String} The formatting string to use.
* @param cSource {String} The source string to use.
* @return {String} The formatted string.
*/
util.printx = function()
{
var formattedValue = "";
if (validateInput.apply(this, arguments))
{
var cFormat = arguments[0].toString();
var cSource = arguments[1].toString();
var sourceIndex = 0;
var currCase = "";
var pattern = /\?+|X+|A+|9+|\*|\\.|>|<|\=/g;
var matches = cFormat.match(pattern);
if (matches)
{
formattedValue += cFormat.substring(0, search(cFormat, matches[0]));
for (var i = 0; i < matches.length; i++)
{
var count = matches[i].length;
formattedValue += getFormattedComponentValue(cSource, matches[i]);
if ((i + 1) < matches.length)
{
var separatorBeginIndex = search(cFormat, matches[i]) + count;
var separatorEndIndex = search(cFormat.slice(separatorBeginIndex), matches[i+1]) + separatorBeginIndex;
formattedValue += cFormat.substring(separatorBeginIndex, separatorEndIndex);
cFormat = cFormat.slice(separatorEndIndex);
}
else
{
var separatorBeginIndex = search(cFormat, matches[i]) + count;
formattedValue += cFormat.slice(separatorBeginIndex);
}
}
}
else
{
formattedValue = cFormat;
}
}
return formattedValue;
/**
* Returns formatted component value.
*
* @private
* @method getFormattedComponentValue
* @param cSource {String} The source string.
* @param match {String} The component match found in the format string.
* @return {String} Formatted component value.
*/
function getFormattedComponentValue(cSource, match)
{
var component = match.charAt(0);
var count = match.length;
var formattedComponentValue = "";
switch (component)
{
case "?":
for (var i = 0; (i < count) && (sourceIndex < cSource.length); i++)
{
if (currCase == "upper")
formattedComponentValue += cSource.charAt(sourceIndex).toUpperCase();
else if (currCase == "lower")
formattedComponentValue += cSource.charAt(sourceIndex).toLowerCase();
else
formattedComponentValue += cSource.charAt(sourceIndex);
sourceIndex++;
}
break;
case "X":
for (var i = 0; (i < count) && (sourceIndex < cSource.length);)
{
if (isAlphaNumeric(cSource.charAt(sourceIndex)))
{
formattedComponentValue += cSource.charAt(sourceIndex);
i++;
}
sourceIndex++;
}
break;
case "A":
for (var i = 0; (i < count) && (sourceIndex < cSource.length);)
{
if (isAlphabetic(cSource.charAt(sourceIndex)))
{
formattedComponentValue += cSource.charAt(sourceIndex);
i++;
}
sourceIndex++;
}
break;
case "9":
for (var i = 0; (i < count) && (sourceIndex < cSource.length);)
{
if (isNumber(cSource.charAt(sourceIndex)))
{
formattedComponentValue += cSource.charAt(sourceIndex);
i++;
}
sourceIndex++;
}
break;
case "*":
formattedComponentValue = cSource.slice(sourceIndex);
break;
case "\\":
formattedComponentValue = match[1];
break;
case ">":
currCase = "upper";
break;
case "<":
currCase = "lower";
break;
case "=":
currCase = "";
break;
}
return formattedComponentValue;
}
/**
* Does input validation for printx method.
*
* @private
* @method validateInput
* @return {Boolean} True if input is valid, otherwise false.
*/
function validateInput()
{
var result = true;
// check if number of arguments are valid
if (!(arguments.length == 2))
{
result = false;
}
else
{
// check if argument 1 is valid
if (isNullOrUndefined(arguments[0]))
{
result = false;
}
// check if argument 2 is valid
if (isNullOrUndefined(arguments[1]))
{
result = false;
}
}
return result;
}
}
/**
* Adds left pad to value.
*
* @private
* @method lpad
* @param value {Number} The value to be left padded.
* @param width {Number} The width in characters of the final string.
* @return {String} Left padded value.
*/
function lpad(value, width)
{
result = value.toString();
while (result.length < width)
result = "0" + result;
return result;
}
/**
* Searches for a string in another string.
*
* @private
* @method search
* @param string {String} The string in which the searchString is to be found.
* @param searchString {String} The search string.
* @return {Number} The index of where the searchString was found in the string.
*/
function search(string, searchString)
{
return string.search(searchString.replace(/\\/g,"\\\\").replace(/\?/g,"\\?").replace(/\*/g,"\\*"));
}
/**
* Checks if the value is either null or undefined.
*
* @private
* @method isNullOrUndefined
* @param value {Any} The value which is to be tested.
* @return {Boolean} True if value is null or undefined, otherwise false.
*/
function isNullOrUndefined(value)
{
if ((value == null) || (value == undefined))
return true;
return false;
}