jsDate attempts to detect locale when loaded and defaults to 'en'.
* If a localization is detected which is not available, jsDate defaults to 'en'.
* Additional localizations can be added after jsDate loads. After adding a localization,
* call the jsDate.regional.getLocale() method. Currently, en, fr and de are defined.
*
* Localizations must be an object and have the following properties defined: monthNames, monthNamesShort, dayNames, dayNamesShort and Localizations are added like:
*
* jsDate.regional['en'] = {
* monthNames : 'January February March April May June July August September October November December'.split(' '),
* monthNamesShort : 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '),
* dayNames : 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' '),
* dayNamesShort : 'Sun Mon Tue Wed Thu Fri Sat'.split(' ')
* };
*
* After adding localizations, call jsDate.regional.getLocale();
to update the locale setting with the
* new localizations.
*/
jsDate.regional = {
'en': {
monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun','Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'fr': {
monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun','Jul','Aoû','Sep','Oct','Nov','Déc'],
dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'de': {
monthNames: ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'],
monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'],
dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'es': {
monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun', 'Jul','Ago','Sep','Oct','Nov','Dic'],
dayNames: ['Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado'],
dayNamesShort: ['Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'ru': {
monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],
monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн','Июл','Авг','Сен','Окт','Ноя','Дек'],
dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],
dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'ar': {
monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'آذار', 'حزيران','تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
dayNames: ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'],
dayNamesShort: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'pt': {
monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'],
dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'],
dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'pt-BR': {
monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho', 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'],
dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'],
dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'pl': {
monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec','Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],
monthNamesShort: ['Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze','Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'],
dayNames: ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'],
dayNamesShort: ['Ni', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'Sb'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'nl': {
monthNames: ['Januari','Februari','Maart','April','Mei','Juni','July','Augustus','September','Oktober','November','December'],
monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Aug','Sep','Okt','Nov','Dec'],
dayNames:','['Zondag','Maandag','Dinsdag','Woensdag','Donderdag','Vrijdag','Zaterdag'],
dayNamesShort: ['Zo','Ma','Di','Wo','Do','Vr','Za'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'sv': {
monthNames: ['januari','februari','mars','april','maj','juni','juli','augusti','september','oktober','november','december'],
monthNamesShort: ['jan','feb','mar','apr','maj','jun','jul','aug','sep','okt','nov','dec'],
dayNames: ['söndag','måndag','tisdag','onsdag','torsdag','fredag','lördag'],
dayNamesShort: ['sön','mån','tis','ons','tor','fre','lör'],
formatString: '%Y-%m-%d %H:%M:%S'
},
'it': {
monthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],
monthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu','Lug','Ago','Set','Ott','Nov','Dic'],
dayNames: ['Domenica','Lunedi','Martedi','Mercoledi','Giovedi','Venerdi','Sabato'],
dayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],
formatString: '%d-%m-%Y %H:%M:%S'
}
};
// Set english variants to 'en'
jsDate.regional['en-US'] = jsDate.regional['en-GB'] = jsDate.regional['en'];
/**
* Try to determine the users locale based on the lang attribute of the html page. Defaults to 'en'
* if it cannot figure out a locale of if the locale does not have a localization defined.
* @returns {String} locale
*/
jsDate.regional.getLocale = function () {
var l = jsDate.config.defaultLocale;
if ( document && document.getElementsByTagName('html') && document.getElementsByTagName('html')[0].lang ) {
l = document.getElementsByTagName('html')[0].lang;
if (!jsDate.regional.hasOwnProperty(l)) {
l = jsDate.config.defaultLocale;
}
}
return l;
};
// ms in day
var day = 24 * 60 * 60 * 1000;
// padd a number with zeros
var addZeros = function(num, digits) {
num = String(num);
var i = digits - num.length;
var s = String(Math.pow(10, i)).slice(1);
return s.concat(num);
};
// representations used for calculating differences between dates.
// This borrows heavily from Ken Snyder's work.
var multipliers = {
millisecond: 1,
second: 1000,
minute: 60 * 1000,
hour: 60 * 60 * 1000,
day: day,
week: 7 * day,
month: {
// add a number of months
add: function(d, number) {
// add any years needed (increments of 12)
multipliers.year.add(d, Math[number > 0 ? 'floor' : 'ceil'](number / 12));
// ensure that we properly wrap betwen December and January
// 11 % 12 = 11
// 12 % 12 = 0
var prevMonth = d.getMonth() + (number % 12);
if (prevMonth == 12) {
prevMonth = 0;
d.setYear(d.getFullYear() + 1);
} else if (prevMonth == -1) {
prevMonth = 11;
d.setYear(d.getFullYear() - 1);
}
d.setMonth(prevMonth);
},
// get the number of months between two Date objects (decimal to the nearest day)
diff: function(d1, d2) {
// get the number of years
var diffYears = d1.getFullYear() - d2.getFullYear();
// get the number of remaining months
var diffMonths = d1.getMonth() - d2.getMonth() + (diffYears * 12);
// get the number of remaining days
var diffDays = d1.getDate() - d2.getDate();
// return the month difference with the days difference as a decimal
return diffMonths + (diffDays / 30);
}
},
year: {
// add a number of years
add: function(d, number) {
d.setYear(d.getFullYear() + Math[number > 0 ? 'floor' : 'ceil'](number));
},
// get the number of years between two Date objects (decimal to the nearest day)
diff: function(d1, d2) {
return multipliers.month.diff(d1, d2) / 12;
}
}
};
//
// Alias each multiplier with an 's' to allow 'year' and 'years' for example.
// This comes from Ken Snyders work.
//
for (var unit in multipliers) {
if (unit.substring(unit.length - 1) != 's') { // IE will iterate newly added properties :|
multipliers[unit + 's'] = multipliers[unit];
}
}
//
// take a jsDate instance and a format code and return the formatted value.
// This is a somewhat modified version of Ken Snyder's method.
//
var format = function(d, code, syntax) {
// if shorcut codes are used, recursively expand those.
if (jsDate.formats[syntax]["shortcuts"][code]) {
return jsDate.strftime(d, jsDate.formats[syntax]["shortcuts"][code], syntax);
} else {
// get the format code function and addZeros() argument
var getter = (jsDate.formats[syntax]["codes"][code] || '').split('.');
var nbr = d['get' + getter[0]] ? d['get' + getter[0]]() : '';
if (getter[1]) {
nbr = addZeros(nbr, getter[1]);
}
return nbr;
}
};
/**
* @static
* Static function for convert a date to a string according to a given format. Also acts as namespace for strftime format codes.
* strftime formatting can be accomplished without creating a jsDate object by calling jsDate.strftime():
*
* var formattedDate = jsDate.strftime('Feb 8, 2006 8:48:32', '%Y-%m-%d %H:%M:%S');
*
* @param {String | Number | Array | jsDate Object | Date Object} date A parsable date string, JavaScript time stamp, Array of form [year, month, day, hours, minutes, seconds, milliseconds], jsDate Object or Date object.
* @param {String} formatString String with embedded date formatting codes.
* See: {@link jsDate.formats}.
* @param {String} syntax Optional syntax to use [default perl].
* @param {String} locale Optional locale to use.
* @returns {String} Formatted representation of the date.
*/
//
// Logic as implemented here is very similar to Ken Snyder's Date Instance Methods.
//
jsDate.strftime = function(d, formatString, syntax, locale) {
var syn = 'perl';
var loc = jsDate.regional.getLocale();
// check if syntax and locale are available or reversed
if (syntax && jsDate.formats.hasOwnProperty(syntax)) {
syn = syntax;
}
else if (syntax && jsDate.regional.hasOwnProperty(syntax)) {
loc = syntax;
}
if (locale && jsDate.formats.hasOwnProperty(locale)) {
syn = locale;
}
else if (locale && jsDate.regional.hasOwnProperty(locale)) {
loc = locale;
}
if (get_type(d) != "[object Object]" || d._type != "jsDate") {
d = new jsDate(d);
d.locale = loc;
}
if (!formatString) {
formatString = d.formatString || jsDate.regional[loc]['formatString'];
}
// default the format string to year-month-day
var source = formatString || '%Y-%m-%d',
result = '',
match;
// replace each format code
while (source.length > 0) {
if (match = source.match(jsDate.formats[syn].codes.matcher)) {
result += source.slice(0, match.index);
result += (match[1] || '') + format(d, match[2], syn);
source = source.slice(match.index + match[0].length);
} else {
result += source;
source = '';
}
}
return result;
};
/**
* @namespace
* Namespace to hold format codes and format shortcuts. "perl" and "php" format codes
* and shortcuts are defined by default. Additional codes and shortcuts can be
* added like:
*
*
* jsDate.formats["perl"] = {
* "codes": {
* matcher: /someregex/,
* Y: "fullYear", // name of "get" method without the "get",
* ..., // more codes
* },
* "shortcuts": {
* F: '%Y-%m-%d',
* ..., // more shortcuts
* }
* };
*
*
* Additionally, ISO and SQL shortcuts are defined and can be accesses via:
* jsDate.formats.ISO
and jsDate.formats.SQL
*/
jsDate.formats = {
ISO:'%Y-%m-%dT%H:%M:%S.%N%G',
SQL:'%Y-%m-%d %H:%M:%S'
};
/**
* Perl format codes and shortcuts for strftime.
*
* A hash (object) of codes where each code must be an array where the first member is
* the name of a Date.prototype or jsDate.prototype function to call
* and optionally a second member indicating the number to pass to addZeros()
*
*
The following format codes are defined:
*
*
* Code Result Description
* == Years ==
* %Y 2008 Four-digit year
* %y 08 Two-digit year
*
* == Months ==
* %m 09 Two-digit month
* %#m 9 One or two-digit month
* %B September Full month name
* %b Sep Abbreviated month name
*
* == Days ==
* %d 05 Two-digit day of month
* %#d 5 One or two-digit day of month
* %e 5 One or two-digit day of month
* %A Sunday Full name of the day of the week
* %a Sun Abbreviated name of the day of the week
* %w 0 Number of the day of the week (0 = Sunday, 6 = Saturday)
*
* == Hours ==
* %H 23 Hours in 24-hour format (two digits)
* %#H 3 Hours in 24-hour integer format (one or two digits)
* %I 11 Hours in 12-hour format (two digits)
* %#I 3 Hours in 12-hour integer format (one or two digits)
* %p PM AM or PM
*
* == Minutes ==
* %M 09 Minutes (two digits)
* %#M 9 Minutes (one or two digits)
*
* == Seconds ==
* %S 02 Seconds (two digits)
* %#S 2 Seconds (one or two digits)
* %s 1206567625723 Unix timestamp (Seconds past 1970-01-01 00:00:00)
*
* == Milliseconds ==
* %N 008 Milliseconds (three digits)
* %#N 8 Milliseconds (one to three digits)
*
* == Timezone ==
* %O 360 difference in minutes between local time and GMT
* %Z Mountain Standard Time Name of timezone as reported by browser
* %G 06:00 Hours and minutes between GMT
*
* == Shortcuts ==
* %F 2008-03-26 %Y-%m-%d
* %T 05:06:30 %H:%M:%S
* %X 05:06:30 %H:%M:%S
* %x 03/26/08 %m/%d/%y
* %D 03/26/08 %m/%d/%y
* %#c Wed Mar 26 15:31:00 2008 %a %b %e %H:%M:%S %Y
* %v 3-Sep-2008 %e-%b-%Y
* %R 15:31 %H:%M
* %r 03:31:00 PM %I:%M:%S %p
*
* == Characters ==
* %n \n Newline
* %t \t Tab
* %% % Percent Symbol
*
*
* Formatting shortcuts that will be translated into their longer version.
* Be sure that format shortcuts do not refer to themselves: this will cause an infinite loop.
*
* Format codes and format shortcuts can be redefined after the jsDate
* module is imported.
*
* Note that if you redefine the whole hash (object), you must supply a "matcher"
* regex for the parser. The default matcher is:
*
* /()%(#?(%|[a-z]))/i
*
* which corresponds to the Perl syntax used by default.
*
* By customizing the matcher and format codes, nearly any strftime functionality is possible.
*/
jsDate.formats.perl = {
codes: {
//
// 2-part regex matcher for format codes
//
// first match must be the character before the code (to account for escaping)
// second match must be the format code character(s)
//
matcher: /()%(#?(%|[a-z]))/i,
// year
Y: 'FullYear',
y: 'ShortYear.2',
// month
m: 'MonthNumber.2',
'#m': 'MonthNumber',
B: 'MonthName',
b: 'AbbrMonthName',
// day
d: 'Date.2',
'#d': 'Date',
e: 'Date',
A: 'DayName',
a: 'AbbrDayName',
w: 'Day',
// hours
H: 'Hours.2',
'#H': 'Hours',
I: 'Hours12.2',
'#I': 'Hours12',
p: 'AMPM',
// minutes
M: 'Minutes.2',
'#M': 'Minutes',
// seconds
S: 'Seconds.2',
'#S': 'Seconds',
s: 'Unix',
// milliseconds
N: 'Milliseconds.3',
'#N': 'Milliseconds',
// timezone
O: 'TimezoneOffset',
Z: 'TimezoneName',
G: 'GmtOffset'
},
shortcuts: {
// date
F: '%Y-%m-%d',
// time
T: '%H:%M:%S',
X: '%H:%M:%S',
// local format date
x: '%m/%d/%y',
D: '%m/%d/%y',
// local format extended
'#c': '%a %b %e %H:%M:%S %Y',
// local format short
v: '%e-%b-%Y',
R: '%H:%M',
r: '%I:%M:%S %p',
// tab and newline
t: '\t',
n: '\n',
'%': '%'
}
};
/**
* PHP format codes and shortcuts for strftime.
*
* A hash (object) of codes where each code must be an array where the first member is
* the name of a Date.prototype or jsDate.prototype function to call
* and optionally a second member indicating the number to pass to addZeros()
*
* The following format codes are defined:
*
*
* Code Result Description
* === Days ===
* %a Sun through Sat An abbreviated textual representation of the day
* %A Sunday - Saturday A full textual representation of the day
* %d 01 to 31 Two-digit day of the month (with leading zeros)
* %e 1 to 31 Day of the month, with a space preceding single digits.
* %j 001 to 366 Day of the year, 3 digits with leading zeros
* %u 1 - 7 (Mon - Sun) ISO-8601 numeric representation of the day of the week
* %w 0 - 6 (Sun - Sat) Numeric representation of the day of the week
*
* === Week ===
* %U 13 Full Week number, starting with the first Sunday as the first week
* %V 01 through 53 ISO-8601:1988 week number, starting with the first week of the year
* with at least 4 weekdays, with Monday being the start of the week
* %W 46 A numeric representation of the week of the year,
* starting with the first Monday as the first week
* === Month ===
* %b Jan through Dec Abbreviated month name, based on the locale
* %B January - December Full month name, based on the locale
* %h Jan through Dec Abbreviated month name, based on the locale (an alias of %b)
* %m 01 - 12 (Jan - Dec) Two digit representation of the month
*
* === Year ===
* %C 19 Two digit century (year/100, truncated to an integer)
* %y 09 for 2009 Two digit year
* %Y 2038 Four digit year
*
* === Time ===
* %H 00 through 23 Two digit representation of the hour in 24-hour format
* %I 01 through 12 Two digit representation of the hour in 12-hour format
* %l 1 through 12 Hour in 12-hour format, with a space preceeding single digits
* %M 00 through 59 Two digit representation of the minute
* %p AM/PM UPPER-CASE 'AM' or 'PM' based on the given time
* %P am/pm lower-case 'am' or 'pm' based on the given time
* %r 09:34:17 PM Same as %I:%M:%S %p
* %R 00:35 Same as %H:%M
* %S 00 through 59 Two digit representation of the second
* %T 21:34:17 Same as %H:%M:%S
* %X 03:59:16 Preferred time representation based on locale, without the date
* %z -0500 or EST Either the time zone offset from UTC or the abbreviation
* %Z -0500 or EST The time zone offset/abbreviation option NOT given by %z
*
* === Time and Date ===
* %D 02/05/09 Same as %m/%d/%y
* %F 2009-02-05 Same as %Y-%m-%d (commonly used in database datestamps)
* %s 305815200 Unix Epoch Time timestamp (same as the time() function)
* %x 02/05/09 Preferred date representation, without the time
*
* === Miscellaneous ===
* %n --- A newline character (\n)
* %t --- A Tab character (\t)
* %% --- A literal percentage character (%)
*
*/
jsDate.formats.php = {
codes: {
//
// 2-part regex matcher for format codes
//
// first match must be the character before the code (to account for escaping)
// second match must be the format code character(s)
//
matcher: /()%((%|[a-z]))/i,
// day
a: 'AbbrDayName',
A: 'DayName',
d: 'Date.2',
e: 'Date',
j: 'DayOfYear.3',
u: 'DayOfWeek',
w: 'Day',
// week
U: 'FullWeekOfYear.2',
V: 'IsoWeek.2',
W: 'WeekOfYear.2',
// month
b: 'AbbrMonthName',
B: 'MonthName',
m: 'MonthNumber.2',
h: 'AbbrMonthName',
// year
C: 'Century.2',
y: 'ShortYear.2',
Y: 'FullYear',
// time
H: 'Hours.2',
I: 'Hours12.2',
l: 'Hours12',
p: 'AMPM',
P: 'AmPm',
M: 'Minutes.2',
S: 'Seconds.2',
s: 'Unix',
O: 'TimezoneOffset',
z: 'GmtOffset',
Z: 'TimezoneAbbr'
},
shortcuts: {
D: '%m/%d/%y',
F: '%Y-%m-%d',
T: '%H:%M:%S',
X: '%H:%M:%S',
x: '%m/%d/%y',
R: '%H:%M',
r: '%I:%M:%S %p',
t: '\t',
n: '\n',
'%': '%'
}
};
//
// Conceptually, the logic implemented here is similar to Ken Snyder's Date Instance Methods.
// I use his idea of a set of parsers which can be regular expressions or functions,
// iterating through those, and then seeing if Date.parse() will create a date.
// The parser expressions and functions are a little different and some bugs have been
// worked out. Also, a lot of "pre-parsing" is done to fix implementation
// variations of Date.parse() between browsers.
//
jsDate.createDate = function(date) {
// if passing in multiple arguments, try Date constructor
if (date == null) {
return new Date();
}
// If the passed value is already a date object, return it
if (date instanceof Date) {
return date;
}
// if (typeof date == 'number') return new Date(date * 1000);
// If the passed value is an integer, interpret it as a javascript timestamp
if (typeof date == 'number') {
return new Date(date);
}
// Before passing strings into Date.parse(), have to normalize them for certain conditions.
// If strings are not formatted staccording to the EcmaScript spec, results from Date parse will be implementation dependent.
//
// For example:
// * FF and Opera assume 2 digit dates are pre y2k, Chome assumes <50 is pre y2k, 50+ is 21st century.
// * Chrome will correctly parse '1984-1-25' into localtime, FF and Opera will not parse.
// * Both FF, Chrome and Opera will parse '1984/1/25' into localtime.
// remove leading and trailing spaces
var parsable = String(date).replace(/^\s*(.+)\s*$/g, '$1');
// replace dahses (-) with slashes (/) in dates like n[nnn]/n[n]/n[nnn]
parsable = parsable.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/, "$1/$2/$3");
/////////
// Need to check for '15-Dec-09' also.
// FF will not parse, but Chrome will.
// Chrome will set date to 2009 as well.
/////////
// first check for 'dd-mmm-yyyy' or 'dd/mmm/yyyy' like '15-Dec-2010'
parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i, "$1 $2 $3");
// Now check for 'dd-mmm-yy' or 'dd/mmm/yy' and normalize years to default century.
var match = parsable.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i);
if (match && match.length > 3) {
var m3 = parseFloat(match[3]);
var ny = jsDate.config.defaultCentury + m3;
ny = String(ny);
// now replace 2 digit year with 4 digit year
parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i, match[1] +' '+ match[2] +' '+ ny);
}
// Check for '1/19/70 8:14PM'
// where starts with mm/dd/yy or yy/mm/dd and have something after
// Check if 1st postiion is greater than 31, assume it is year.
// Assme all 2 digit years are 1900's.
// Finally, change them into US style mm/dd/yyyy representations.
match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/);
function h1(parsable, match) {
var m1 = parseFloat(match[1]);
var m2 = parseFloat(match[2]);
var m3 = parseFloat(match[3]);
var cent = jsDate.config.defaultCentury;
var ny, nd, nm, str;
if (m1 > 31) { // first number is a year
nd = m3;
nm = m2;
ny = cent + m1;
}
else { // last number is the year
nd = m2;
nm = m1;
ny = cent + m3;
}
str = nm+'/'+nd+'/'+ny;
// now replace 2 digit year with 4 digit year
return parsable.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/, str);
}
if (match && match.length > 3) {
parsable = h1(parsable, match);
}
// Now check for '1/19/70' with nothing after and do as above
var match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/);
if (match && match.length > 3) {
parsable = h1(parsable, match);
}
var i = 0;
var length = jsDate.matchers.length;
var pattern,
ms,
current = parsable,
obj;
while (i < length) {
ms = Date.parse(current);
if (!isNaN(ms)) {
return new Date(ms);
}
pattern = jsDate.matchers[i];
if (typeof pattern == 'function') {
obj = pattern.call(jsDate, current);
if (obj instanceof Date) {
return obj;
}
} else {
current = parsable.replace(pattern[0], pattern[1]);
}
i++;
}
return NaN;
};
/**
* @static
* Handy static utility function to return the number of days in a given month.
* @param {Integer} year Year
* @param {Integer} month Month (1-12)
* @returns {Integer} Number of days in the month.
*/
//
// handy utility method Borrowed right from Ken Snyder's Date Instance Mehtods.
//
jsDate.daysInMonth = function(year, month) {
if (month == 2) {
return new Date(year, 1, 29).getDate() == 29 ? 29 : 28;
}
return [undefined,31,undefined,31,30,31,30,31,31,30,31,30,31][month];
};
//
// An Array of regular expressions or functions that will attempt to match the date string.
// Functions are called with scope of a jsDate instance.
//
jsDate.matchers = [
// convert dd.mmm.yyyy to mm/dd/yyyy (world date to US date).
[/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/, '$2/$1/$3'],
// convert yyyy-mm-dd to mm/dd/yyyy (ISO date to US date).
[/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/, '$2/$3/$1'],
// Handle 12 hour or 24 hour time with milliseconds am/pm and optional date part.
function(str) {
var match = str.match(/^(?:(.+)\s+)?([012]?\d)(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d(\.\d*)?))?\s*(am|pm)?\s*$/i);
// opt. date hour opt. minute opt. second opt. msec opt. am or pm
if (match) {
if (match[1]) {
var d = this.createDate(match[1]);
if (isNaN(d)) {
return;
}
} else {
var d = new Date();
d.setMilliseconds(0);
}
var hour = parseFloat(match[2]);
if (match[6]) {
hour = match[6].toLowerCase() == 'am' ? (hour == 12 ? 0 : hour) : (hour == 12 ? 12 : hour + 12);
}
d.setHours(hour, parseInt(match[3] || 0, 10), parseInt(match[4] || 0, 10), ((parseFloat(match[5] || 0)) || 0)*1000);
return d;
}
else {
return str;
}
},
// Handle ISO timestamp with time zone.
function(str) {
var match = str.match(/^(?:(.+))[T|\s+]([012]\d)(?:\:(\d\d))(?:\:(\d\d))(?:\.\d+)([\+\-]\d\d\:\d\d)$/i);
if (match) {
if (match[1]) {
var d = this.createDate(match[1]);
if (isNaN(d)) {
return;
}
} else {
var d = new Date();
d.setMilliseconds(0);
}
var hour = parseFloat(match[2]);
d.setHours(hour, parseInt(match[3], 10), parseInt(match[4], 10), parseFloat(match[5])*1000);
return d;
}
else {
return str;
}
},
// Try to match ambiguous strings like 12/8/22.
// Use FF date assumption that 2 digit years are 20th century (i.e. 1900's).
// This may be redundant with pre processing of date already performed.
function(str) {
var match = str.match(/^([0-3]?\d)\s*[-\/.\s]{1}\s*([a-zA-Z]{3,9})\s*[-\/.\s]{1}\s*([0-3]?\d)$/);
if (match) {
var d = new Date();
var cent = jsDate.config.defaultCentury;
var m1 = parseFloat(match[1]);
var m3 = parseFloat(match[3]);
var ny, nd, nm;
if (m1 > 31) { // first number is a year
nd = m3;
ny = cent + m1;
}
else { // last number is the year
nd = m1;
ny = cent + m3;
}
var nm = inArray(match[2], jsDate.regional[jsDate.regional.getLocale()]["monthNamesShort"]);
if (nm == -1) {
nm = inArray(match[2], jsDate.regional[jsDate.regional.getLocale()]["monthNames"]);
}
d.setFullYear(ny, nm, nd);
d.setHours(0,0,0,0);
return d;
}
else {
return str;
}
}
];
//
// I think John Reisig published this method on his blog, ejohn.
//
function inArray( elem, array ) {
if ( array.indexOf ) {
return array.indexOf( elem );
}
for ( var i = 0, length = array.length; i < length; i++ ) {
if ( array[ i ] === elem ) {
return i;
}
}
return -1;
}
//
// Thanks to Kangax, Christian Sciberras and Stack Overflow for this method.
//
function get_type(thing){
if(thing===null) return "[object Null]"; // special case
return Object.prototype.toString.call(thing);
}
$.jsDate = jsDate;
/**
* JavaScript printf/sprintf functions.
*
* This code has been adapted from the publicly available sprintf methods
* by Ash Searle. His original header follows:
*
* This code is unrestricted: you are free to use it however you like.
*
* The functions should work as expected, performing left or right alignment,
* truncating strings, outputting numbers with a required precision etc.
*
* For complex cases, these functions follow the Perl implementations of
* (s)printf, allowing arguments to be passed out-of-order, and to set the
* precision or length of the output based on arguments instead of fixed
* numbers.
*
* See http://perldoc.perl.org/functions/sprintf.html for more information.
*
* Implemented:
* - zero and space-padding
* - right and left-alignment,
* - base X prefix (binary, octal and hex)
* - positive number prefix
* - (minimum) width
* - precision / truncation / maximum width
* - out of order arguments
*
* Not implemented (yet):
* - vector flag
* - size (bytes, words, long-words etc.)
*
* Will not implement:
* - %n or %p (no pass-by-reference in JavaScript)
*
* @version 2007.04.27
* @author Ash Searle
*
* You can see the original work and comments on his blog:
* http://hexmen.com/blog/2007/03/printf-sprintf/
* http://hexmen.com/js/sprintf.js
*/
/**
* @Modifications 2009.05.26
* @author Chris Leonello
*
* Added %p %P specifier
* Acts like %g or %G but will not add more significant digits to the output than present in the input.
* Example:
* Format: '%.3p', Input: 0.012, Output: 0.012
* Format: '%.3g', Input: 0.012, Output: 0.0120
* Format: '%.4p', Input: 12.0, Output: 12.0
* Format: '%.4g', Input: 12.0, Output: 12.00
* Format: '%.4p', Input: 4.321e-5, Output: 4.321e-5
* Format: '%.4g', Input: 4.321e-5, Output: 4.3210e-5
*
* Example:
* >>> $.jqplot.sprintf('%.2f, %d', 23.3452, 43.23)
* "23.35, 43"
* >>> $.jqplot.sprintf("no value: %n, decimal with thousands separator: %'d", 23.3452, 433524)
* "no value: , decimal with thousands separator: 433,524"
*/
$.jqplot.sprintf = function() {
function pad(str, len, chr, leftJustify) {
var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
return leftJustify ? str + padding : padding + str;
}
function thousand_separate(value) {
var value_str = new String(value);
for (var i=10; i>0; i--) {
if (value_str == (value_str = value_str.replace(/^(\d+)(\d{3})/, "$1"+$.jqplot.sprintf.thousandsSeparator+"$2"))) break;
}
return value_str;
}
function justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace) {
var diff = minWidth - value.length;
if (diff > 0) {
var spchar = ' ';
if (htmlSpace) { spchar = ' '; }
if (leftJustify || !zeroPad) {
value = pad(value, minWidth, spchar, leftJustify);
} else {
value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
}
}
return value;
}
function formatBaseX(value, base, prefix, leftJustify, minWidth, precision, zeroPad, htmlSpace) {
// Note: casts negative numbers to positive ones
var number = value >>> 0;
prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || '';
value = prefix + pad(number.toString(base), precision || 0, '0', false);
return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace);
}
function formatString(value, leftJustify, minWidth, precision, zeroPad, htmlSpace) {
if (precision != null) {
value = value.slice(0, precision);
}
return justify(value, '', leftJustify, minWidth, zeroPad, htmlSpace);
}
var a = arguments, i = 0, format = a[i++];
return format.replace($.jqplot.sprintf.regex, function(substring, valueIndex, flags, minWidth, _, precision, type) {
if (substring == '%%') { return '%'; }
// parse flags
var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, htmlSpace = false, thousandSeparation = false;
for (var j = 0; flags && j < flags.length; j++) switch (flags.charAt(j)) {
case ' ': positivePrefix = ' '; break;
case '+': positivePrefix = '+'; break;
case '-': leftJustify = true; break;
case '0': zeroPad = true; break;
case '#': prefixBaseX = true; break;
case '&': htmlSpace = true; break;
case '\'': thousandSeparation = true; break;
}
// parameters may be null, undefined, empty-string or real valued
// we want to ignore null, undefined and empty-string values
if (!minWidth) {
minWidth = 0;
}
else if (minWidth == '*') {
minWidth = +a[i++];
}
else if (minWidth.charAt(0) == '*') {
minWidth = +a[minWidth.slice(1, -1)];
}
else {
minWidth = +minWidth;
}
// Note: undocumented perl feature:
if (minWidth < 0) {
minWidth = -minWidth;
leftJustify = true;
}
if (!isFinite(minWidth)) {
throw new Error('$.jqplot.sprintf: (minimum-)width must be finite');
}
if (!precision) {
precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0);
}
else if (precision == '*') {
precision = +a[i++];
}
else if (precision.charAt(0) == '*') {
precision = +a[precision.slice(1, -1)];
}
else {
precision = +precision;
}
// grab value using valueIndex if required?
var value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];
switch (type) {
case 's': {
if (value == null) {
return '';
}
return formatString(String(value), leftJustify, minWidth, precision, zeroPad, htmlSpace);
}
case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad, htmlSpace);
case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad,htmlSpace);
case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace);
case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace);
case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace).toUpperCase();
case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace);
case 'i': {
var number = parseInt(+value, 10);
if (isNaN(number)) {
return '';
}
var prefix = number < 0 ? '-' : positivePrefix;
var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number));
value = prefix + pad(number_str, precision, '0', false);
//value = prefix + pad(String(Math.abs(number)), precision, '0', false);
return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace);
}
case 'd': {
var number = Math.round(+value);
if (isNaN(number)) {
return '';
}
var prefix = number < 0 ? '-' : positivePrefix;
var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number));
value = prefix + pad(number_str, precision, '0', false);
return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace);
}
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
{
var number = +value;
if (isNaN(number)) {
return '';
}
var prefix = number < 0 ? '-' : positivePrefix;
var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
var number_str = Math.abs(number)[method](precision);
// Apply the decimal mark properly by splitting the number by the
// decimalMark, applying thousands separator, and then placing it
// back in.
var parts = number_str.toString().split('.');
parts[0] = thousandSeparation ? thousand_separate(parts[0]) : parts[0];
number_str = parts.join($.jqplot.sprintf.decimalMark);
value = prefix + number_str;
var justified = justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform]();
return justified;
}
case 'p':
case 'P':
{
// make sure number is a number
var number = +value;
if (isNaN(number)) {
return '';
}
var prefix = number < 0 ? '-' : positivePrefix;
var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/);
var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : String(number).length;
var zeros = (parts[1] < 0) ? -parts[1] - 1 : 0;
if (Math.abs(number) < 1) {
if (sd + zeros <= precision) {
value = prefix + Math.abs(number).toPrecision(sd);
}
else {
if (sd <= precision - 1) {
value = prefix + Math.abs(number).toExponential(sd-1);
}
else {
value = prefix + Math.abs(number).toExponential(precision-1);
}
}
}
else {
var prec = (sd <= precision) ? sd : precision;
value = prefix + Math.abs(number).toPrecision(prec);
}
var textTransform = ['toString', 'toUpperCase']['pP'.indexOf(type) % 2];
return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform]();
}
case 'n': return '';
default: return substring;
}
});
};
$.jqplot.sprintf.thousandsSeparator = ',';
// Specifies the decimal mark for floating point values. By default a period '.'
// is used. If you change this value to for example a comma be sure to also
// change the thousands separator or else this won't work since a simple String
// replace is used (replacing all periods with the mark specified here).
$.jqplot.sprintf.decimalMark = '.';
$.jqplot.sprintf.regex = /%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g;
$.jqplot.getSignificantFigures = function(number) {
var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/);
// total significant digits
var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : parts[0].length;
var zeros = (parts[1] < 0) ? -parts[1] - 1 : 0;
// exponent
var expn = parseInt(parts[1], 10);
// digits to the left of the decimal place
var dleft = (expn + 1 > 0) ? expn + 1 : 0;
// digits to the right of the decimal place
var dright = (sd <= dleft) ? 0 : sd - expn - 1;
return {significantDigits: sd, digitsLeft: dleft, digitsRight: dright, zeros: zeros, exponent: expn} ;
};
$.jqplot.getPrecision = function(number) {
return $.jqplot.getSignificantFigures(number).digitsRight;
};
var backCompat = $.uiBackCompat !== false;
$.jqplot.effects = {
effect: {}
};
// prefix used for storing data on .data()
var dataSpace = "jqplot.storage.";
/******************************************************************************/
/*********************************** EFFECTS **********************************/
/******************************************************************************/
$.extend( $.jqplot.effects, {
version: "1.9pre",
// Saves a set of properties in a data storage
save: function( element, set ) {
for( var i=0; i < set.length; i++ ) {
if ( set[ i ] !== null ) {
element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
}
}
},
// Restores a set of previously saved properties from a data storage
restore: function( element, set ) {
for( var i=0; i < set.length; i++ ) {
if ( set[ i ] !== null ) {
element.css( set[ i ], element.data( dataSpace + set[ i ] ) );
}
}
},
setMode: function( el, mode ) {
if (mode === "toggle") {
mode = el.is( ":hidden" ) ? "show" : "hide";
}
return mode;
},
// Wraps the element around a wrapper that copies position properties
createWrapper: function( element ) {
// if the element is already wrapped, return it
if ( element.parent().is( ".ui-effects-wrapper" )) {
return element.parent();
}
// wrap the element
var props = {
width: element.outerWidth(true),
height: element.outerHeight(true),
"float": element.css( "float" )
},
wrapper = $( "" )
.addClass( "ui-effects-wrapper" )
.css({
fontSize: "100%",
background: "transparent",
border: "none",
margin: 0,
padding: 0
}),
// Store the size in case width/height are defined in % - Fixes #5245
size = {
width: element.width(),
height: element.height()
},
active = document.activeElement;
element.wrap( wrapper );
// Fixes #7595 - Elements lose focus when wrapped.
if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
$( active ).focus();
}
wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
// transfer positioning properties to the wrapper
if ( element.css( "position" ) === "static" ) {
wrapper.css({ position: "relative" });
element.css({ position: "relative" });
} else {
$.extend( props, {
position: element.css( "position" ),
zIndex: element.css( "z-index" )
});
$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
props[ pos ] = element.css( pos );
if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
props[ pos ] = "auto";
}
});
element.css({
position: "relative",
top: 0,
left: 0,
right: "auto",
bottom: "auto"
});
}
element.css(size);
return wrapper.css( props ).show();
},
removeWrapper: function( element ) {
var active = document.activeElement;
if ( element.parent().is( ".ui-effects-wrapper" ) ) {
element.parent().replaceWith( element );
// Fixes #7595 - Elements lose focus when wrapped.
if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
$( active ).focus();
}
}
return element;
}
});
// return an effect options object for the given parameters:
function _normalizeArguments( effect, options, speed, callback ) {
// short path for passing an effect options object:
if ( $.isPlainObject( effect ) ) {
return effect;
}
// convert to an object
effect = { effect: effect };
// catch (effect)
if ( options === undefined ) {
options = {};
}
// catch (effect, callback)
if ( $.isFunction( options ) ) {
callback = options;
speed = null;
options = {};
}
// catch (effect, speed, ?)
if ( $.type( options ) === "number" || $.fx.speeds[ options ]) {
callback = speed;
speed = options;
options = {};
}
// catch (effect, options, callback)
if ( $.isFunction( speed ) ) {
callback = speed;
speed = null;
}
// add options to effect
if ( options ) {
$.extend( effect, options );
}
speed = speed || options.duration;
effect.duration = $.fx.off ? 0 : typeof speed === "number"
? speed : speed in $.fx.speeds ? $.fx.speeds[ speed ] : $.fx.speeds._default;
effect.complete = callback || options.complete;
return effect;
}
function standardSpeed( speed ) {
// valid standard speeds
if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
return true;
}
// invalid strings - treat as "normal" speed
if ( typeof speed === "string" && !$.jqplot.effects.effect[ speed ] ) {
// TODO: remove in 2.0 (#7115)
if ( backCompat && $.jqplot.effects[ speed ] ) {
return false;
}
return true;
}
return false;
}
$.fn.extend({
jqplotEffect: function( effect, options, speed, callback ) {
var args = _normalizeArguments.apply( this, arguments ),
mode = args.mode,
queue = args.queue,
effectMethod = $.jqplot.effects.effect[ args.effect ],
// DEPRECATED: remove in 2.0 (#7115)
oldEffectMethod = !effectMethod && backCompat && $.jqplot.effects[ args.effect ];
if ( $.fx.off || !( effectMethod || oldEffectMethod ) ) {
// delegate to the original method (e.g., .show()) if possible
if ( mode ) {
return this[ mode ]( args.duration, args.complete );
} else {
return this.each( function() {
if ( args.complete ) {
args.complete.call( this );
}
});
}
}
function run( next ) {
var elem = $( this ),
complete = args.complete,
mode = args.mode;
function done() {
if ( $.isFunction( complete ) ) {
complete.call( elem[0] );
}
if ( $.isFunction( next ) ) {
next();
}
}
// if the element is hiddden and mode is hide,
// or element is visible and mode is show
if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
done();
} else {
effectMethod.call( elem[0], args, done );
}
}
// TODO: remove this check in 2.0, effectMethod will always be true
if ( effectMethod ) {
return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
} else {
// DEPRECATED: remove in 2.0 (#7115)
return oldEffectMethod.call(this, {
options: args,
duration: args.duration,
callback: args.complete,
mode: args.mode
});
}
}
});
var rvertical = /up|down|vertical/,
rpositivemotion = /up|left|vertical|horizontal/;
$.jqplot.effects.effect.blind = function( o, done ) {
// Create element
var el = $( this ),
props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
mode = $.jqplot.effects.setMode( el, o.mode || "hide" ),
direction = o.direction || "up",
vertical = rvertical.test( direction ),
ref = vertical ? "height" : "width",
ref2 = vertical ? "top" : "left",
motion = rpositivemotion.test( direction ),
animation = {},
show = mode === "show",
wrapper, distance, top;
// // if already wrapped, the wrapper's properties are my property. #6245
if ( el.parent().is( ".ui-effects-wrapper" ) ) {
$.jqplot.effects.save( el.parent(), props );
} else {
$.jqplot.effects.save( el, props );
}
el.show();
top = parseInt(el.css('top'), 10);
wrapper = $.jqplot.effects.createWrapper( el ).css({
overflow: "hidden"
});
distance = vertical ? wrapper[ ref ]() + top : wrapper[ ref ]();
animation[ ref ] = show ? String(distance) : '0';
if ( !motion ) {
el
.css( vertical ? "bottom" : "right", 0 )
.css( vertical ? "top" : "left", "" )
.css({ position: "absolute" });
animation[ ref2 ] = show ? '0' : String(distance);
}
// // start at 0 if we are showing
if ( show ) {
wrapper.css( ref, 0 );
if ( ! motion ) {
wrapper.css( ref2, distance );
}
}
// // Animate
wrapper.animate( animation, {
duration: o.duration,
easing: o.easing,
queue: false,
complete: function() {
if ( mode === "hide" ) {
el.hide();
}
$.jqplot.effects.restore( el, props );
$.jqplot.effects.removeWrapper( el );
done();
}
});
};
})(jQuery);