app.js 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. $.fn.scrollTo = function (target, options, callback) {
  2. if (typeof options == 'function' && arguments.length == 2) {
  3. callback = options;
  4. options = target;
  5. }
  6. var settings = $.extend(
  7. {
  8. scrollTarget: target,
  9. offsetTop: 50,
  10. duration: 10,
  11. easing: 'swing',
  12. },
  13. options
  14. );
  15. return this.each(function () {
  16. var scrollPane = $(this);
  17. var scrollTarget =
  18. typeof settings.scrollTarget == 'number' ? settings.scrollTarget : $(settings.scrollTarget);
  19. var scrollY =
  20. typeof scrollTarget == 'number'
  21. ? scrollTarget
  22. : scrollTarget.offset().top + scrollPane.scrollTop() - parseInt(settings.offsetTop);
  23. scrollPane.animate(
  24. { scrollTop: scrollY },
  25. parseInt(settings.duration),
  26. settings.easing,
  27. function () {
  28. if (typeof callback == 'function') {
  29. callback.call(this);
  30. }
  31. }
  32. );
  33. });
  34. };
  35. /*
  36. * Date Format 1.2.3
  37. * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
  38. * MIT license
  39. *
  40. * Includes enhancements by Scott Trenda <scott.trenda.net>
  41. * and Kris Kowal <cixar.com/~kris.kowal/>
  42. *
  43. * Accepts a date, a mask, or a date and a mask.
  44. * Returns a formatted version of the given date.
  45. * The date defaults to the current date/time.
  46. * The mask defaults to dateFormat.masks.default.
  47. */
  48. var dateFormat = (function () {
  49. var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
  50. timezone =
  51. /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
  52. timezoneClip = /[^-+\dA-Z]/g,
  53. pad = function (val, len) {
  54. val = String(val);
  55. len = len || 2;
  56. while (val.length < len) val = '0' + val;
  57. return val;
  58. };
  59. // Regexes and supporting functions are cached through closure
  60. return function (date, mask, utc) {
  61. var dF = dateFormat;
  62. // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
  63. if (
  64. arguments.length == 1 &&
  65. Object.prototype.toString.call(date) == '[object String]' &&
  66. !/\d/.test(date)
  67. ) {
  68. mask = date;
  69. date = undefined;
  70. }
  71. // Passing date through Date applies Date.parse, if necessary
  72. date = date ? new Date(date) : new Date();
  73. if (isNaN(date)) throw SyntaxError('invalid date');
  74. mask = String(dF.masks[mask] || mask || dF.masks['default']);
  75. // Allow setting the utc argument via the mask
  76. if (mask.slice(0, 4) == 'UTC:') {
  77. mask = mask.slice(4);
  78. utc = true;
  79. }
  80. var _ = utc ? 'getUTC' : 'get',
  81. d = date[_ + 'Date'](),
  82. D = date[_ + 'Day'](),
  83. m = date[_ + 'Month'](),
  84. y = date[_ + 'FullYear'](),
  85. H = date[_ + 'Hours'](),
  86. M = date[_ + 'Minutes'](),
  87. s = date[_ + 'Seconds'](),
  88. L = date[_ + 'Milliseconds'](),
  89. o = utc ? 0 : date.getTimezoneOffset(),
  90. flags = {
  91. d: d,
  92. dd: pad(d),
  93. ddd: dF.i18n.dayNames[D],
  94. dddd: dF.i18n.dayNames[D + 7],
  95. m: m + 1,
  96. mm: pad(m + 1),
  97. mmm: dF.i18n.monthNames[m],
  98. mmmm: dF.i18n.monthNames[m + 12],
  99. yy: String(y).slice(2),
  100. yyyy: y,
  101. h: H % 12 || 12,
  102. hh: pad(H % 12 || 12),
  103. H: H,
  104. HH: pad(H),
  105. M: M,
  106. MM: pad(M),
  107. s: s,
  108. ss: pad(s),
  109. l: pad(L, 3),
  110. L: pad(L > 99 ? Math.round(L / 10) : L),
  111. t: H < 12 ? 'a' : 'p',
  112. tt: H < 12 ? 'am' : 'pm',
  113. T: H < 12 ? 'A' : 'P',
  114. TT: H < 12 ? 'AM' : 'PM',
  115. Z: utc ? 'UTC' : (String(date).match(timezone) || ['']).pop().replace(timezoneClip, ''),
  116. o: (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + (Math.abs(o) % 60), 4),
  117. S: ['th', 'st', 'nd', 'rd'][d % 10 > 3 ? 0 : (((d % 100) - (d % 10) != 10) * d) % 10],
  118. };
  119. return mask.replace(token, function ($0) {
  120. return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
  121. });
  122. };
  123. })();
  124. // Some common format strings
  125. dateFormat.masks = {
  126. default: 'ddd mmm dd yyyy HH:MM:ss',
  127. shortDate: 'm/d/yy',
  128. mediumDate: 'mmm d, yyyy',
  129. longDate: 'mmmm d, yyyy',
  130. fullDate: 'dddd, mmmm d, yyyy',
  131. shortTime: 'h:MM TT',
  132. mediumTime: 'h:MM:ss TT',
  133. longTime: 'h:MM:ss TT Z',
  134. isoDate: 'yyyy-mm-dd',
  135. isoTime: 'HH:MM:ss',
  136. isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
  137. isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'",
  138. };
  139. // Internationalization strings
  140. dateFormat.i18n = {
  141. dayNames: [
  142. 'Sun',
  143. 'Mon',
  144. 'Tue',
  145. 'Wed',
  146. 'Thu',
  147. 'Fri',
  148. 'Sat',
  149. 'Sunday',
  150. 'Monday',
  151. 'Tuesday',
  152. 'Wednesday',
  153. 'Thursday',
  154. 'Friday',
  155. 'Saturday',
  156. ],
  157. monthNames: [
  158. 'Jan',
  159. 'Feb',
  160. 'Mar',
  161. 'Apr',
  162. 'May',
  163. 'Jun',
  164. 'Jul',
  165. 'Aug',
  166. 'Sep',
  167. 'Oct',
  168. 'Nov',
  169. 'Dec',
  170. 'January',
  171. 'February',
  172. 'March',
  173. 'April',
  174. 'May',
  175. 'June',
  176. 'July',
  177. 'August',
  178. 'September',
  179. 'October',
  180. 'November',
  181. 'December',
  182. ],
  183. };
  184. // For convenience...
  185. Date.prototype.format = function (mask, utc) {
  186. return dateFormat(this, mask, utc);
  187. };
  188. /*
  189. * http://code.google.com/p/flexible-js-formatting/
  190. *
  191. * Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
  192. *
  193. * Permission is hereby granted, free of charge, to any person obtaining a copy
  194. * of this software and associated documentation files (the "Software"), to deal
  195. * in the Software without restriction, including without limitation the rights
  196. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  197. * copies of the Software, and to permit persons to whom the Software is
  198. * furnished to do so, subject to the following conditions:
  199. *
  200. * The above copyright notice and this permission notice shall be included in
  201. * all copies or substantial portions of the Software.
  202. *
  203. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  204. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  205. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  206. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  207. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  208. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  209. * THE SOFTWARE.
  210. */
  211. Date.parseFunctions = { count: 0 };
  212. Date.parseRegexes = [];
  213. Date.formatFunctions = { count: 0 };
  214. Date.prototype.dateFormat = function (format, ignore_offset) {
  215. if (Date.formatFunctions[format] == null) {
  216. Date.createNewFormat(format);
  217. }
  218. var func = Date.formatFunctions[format];
  219. if (ignore_offset || !this.offset) {
  220. return this[func]();
  221. } else {
  222. return new Date(this.valueOf() - this.offset)[func]();
  223. }
  224. };
  225. Date.createNewFormat = function (format) {
  226. var funcName = 'format' + Date.formatFunctions.count++;
  227. Date.formatFunctions[format] = funcName;
  228. var code = 'Date.prototype.' + funcName + ' = function(){return ';
  229. var special = false;
  230. var ch = '';
  231. for (var i = 0; i < format.length; ++i) {
  232. ch = format.charAt(i);
  233. // escape character start
  234. if (!special && ch == '\\') {
  235. special = true;
  236. }
  237. // escaped string
  238. else if (!special && ch == '"') {
  239. var end = format.indexOf('"', i + 1);
  240. if (end == -1) {
  241. end = format.length;
  242. }
  243. code += "'" + String.escape(format.substring(i + 1, end)) + "' + ";
  244. i = end;
  245. }
  246. // escaped character
  247. else if (special) {
  248. special = false;
  249. code += "'" + String.escape(ch) + "' + ";
  250. } else {
  251. code += Date.getFormatCode(ch);
  252. }
  253. }
  254. eval(code.substring(0, code.length - 3) + ';}');
  255. };
  256. Date.getFormatCode = function (character) {
  257. switch (character) {
  258. case 'd':
  259. return "String.leftPad(this.getDate(), 2, '0') + ";
  260. case 'D':
  261. return 'Date.dayNames[this.getDay()].substring(0, 3) + ';
  262. case 'j':
  263. return 'this.getDate() + ';
  264. case 'l':
  265. return 'Date.dayNames[this.getDay()] + ';
  266. case 'S':
  267. return 'this.getSuffix() + ';
  268. case 'w':
  269. return 'this.getDay() + ';
  270. case 'z':
  271. return 'this.getDayOfYear() + ';
  272. case 'W':
  273. return 'this.getWeekOfYear() + ';
  274. case 'F':
  275. return 'Date.monthNames[this.getMonth()] + ';
  276. case 'm':
  277. return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
  278. case 'M':
  279. return 'Date.monthNames[this.getMonth()].substring(0, 3) + ';
  280. case 'n':
  281. return '(this.getMonth() + 1) + ';
  282. case 't':
  283. return 'this.getDaysInMonth() + ';
  284. case 'L':
  285. return '(this.isLeapYear() ? 1 : 0) + ';
  286. case 'Y':
  287. return 'this.getFullYear() + ';
  288. case 'y':
  289. return "('' + this.getFullYear()).substring(2, 4) + ";
  290. case 'a':
  291. return "(this.getHours() < 12 ? 'am' : 'pm') + ";
  292. case 'A':
  293. return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
  294. case 'g':
  295. return '((this.getHours() %12) ? this.getHours() % 12 : 12) + ';
  296. case 'G':
  297. return 'this.getHours() + ';
  298. case 'h':
  299. return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";
  300. case 'H':
  301. return "String.leftPad(this.getHours(), 2, '0') + ";
  302. case 'i':
  303. return "String.leftPad(this.getMinutes(), 2, '0') + ";
  304. case 's':
  305. return "String.leftPad(this.getSeconds(), 2, '0') + ";
  306. case 'X':
  307. return "String.leftPad(this.getMilliseconds(), 3, '0') + ";
  308. case 'O':
  309. return 'this.getGMTOffset() + ';
  310. case 'T':
  311. return 'this.getTimezone() + ';
  312. case 'Z':
  313. return '(this.getTimezoneOffset() * -60) + ';
  314. case 'q': // quarter num, Q for name?
  315. return 'this.getQuarter() + ';
  316. default:
  317. return "'" + String.escape(character) + "' + ";
  318. }
  319. };
  320. Date.parseDate = function (input, format) {
  321. if (Date.parseFunctions[format] == null) {
  322. Date.createParser(format);
  323. }
  324. var func = Date.parseFunctions[format];
  325. return Date[func](input);
  326. };
  327. Date.createParser = function (format) {
  328. var funcName = 'parse' + Date.parseFunctions.count++;
  329. var regexNum = Date.parseRegexes.length;
  330. var currentGroup = 1;
  331. Date.parseFunctions[format] = funcName;
  332. var code =
  333. 'Date.' +
  334. funcName +
  335. ' = function(input){\n' +
  336. 'var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, ms = -1, z = 0;\n' +
  337. 'var d = new Date();\n' +
  338. 'y = d.getFullYear();\n' +
  339. 'm = d.getMonth();\n' +
  340. 'd = d.getDate();\n' +
  341. 'var results = input.match(Date.parseRegexes[' +
  342. regexNum +
  343. ']);\n' +
  344. 'if (results && results.length > 0) {';
  345. var regex = '';
  346. var special = false;
  347. var ch = '';
  348. for (var i = 0; i < format.length; ++i) {
  349. ch = format.charAt(i);
  350. if (!special && ch == '\\') {
  351. special = true;
  352. } else if (special) {
  353. special = false;
  354. regex += String.escape(ch);
  355. } else {
  356. obj = Date.formatCodeToRegex(ch, currentGroup);
  357. currentGroup += obj.g;
  358. regex += obj.s;
  359. if (obj.g && obj.c) {
  360. code += obj.c;
  361. }
  362. }
  363. }
  364. code +=
  365. 'if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0 && ms >= 0)\n' +
  366. '{return new Date(y, m, d, h, i, s, ms).applyOffset(z);}\n' +
  367. 'if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n' +
  368. '{return new Date(y, m, d, h, i, s).applyOffset(z);}\n' +
  369. 'else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n' +
  370. '{return new Date(y, m, d, h, i).applyOffset(z);}\n' +
  371. 'else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n' +
  372. '{return new Date(y, m, d, h).applyOffset(z);}\n' +
  373. 'else if (y > 0 && m >= 0 && d > 0)\n' +
  374. '{return new Date(y, m, d).applyOffset(z);}\n' +
  375. 'else if (y > 0 && m >= 0)\n' +
  376. '{return new Date(y, m).applyOffset(z);}\n' +
  377. 'else if (y > 0)\n' +
  378. '{return new Date(y).applyOffset(z);}\n' +
  379. '}return null;}';
  380. Date.parseRegexes[regexNum] = new RegExp('^' + regex + '$');
  381. eval(code);
  382. };
  383. Date.formatCodeToRegex = function (character, currentGroup) {
  384. switch (character) {
  385. case 'D':
  386. return { g: 0, c: null, s: '(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)' };
  387. case 'j':
  388. case 'd':
  389. return { g: 1, c: 'd = parseInt(results[' + currentGroup + '], 10);\n', s: '(\\d{1,2})' };
  390. case 'l':
  391. return { g: 0, c: null, s: '(?:' + Date.dayNames.join('|') + ')' };
  392. case 'S':
  393. return { g: 0, c: null, s: '(?:st|nd|rd|th)' };
  394. case 'w':
  395. return { g: 0, c: null, s: '\\d' };
  396. case 'z':
  397. return { g: 0, c: null, s: '(?:\\d{1,3})' };
  398. case 'W':
  399. return { g: 0, c: null, s: '(?:\\d{2})' };
  400. case 'F':
  401. return {
  402. g: 1,
  403. c: 'm = parseInt(Date.monthNumbers[results[' + currentGroup + '].substring(0, 3)], 10);\n',
  404. s: '(' + Date.monthNames.join('|') + ')',
  405. };
  406. case 'M':
  407. return {
  408. g: 1,
  409. c: 'm = parseInt(Date.monthNumbers[results[' + currentGroup + ']], 10);\n',
  410. s: '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)',
  411. };
  412. case 'n':
  413. case 'm':
  414. return { g: 1, c: 'm = parseInt(results[' + currentGroup + '], 10) - 1;\n', s: '(\\d{1,2})' };
  415. case 't':
  416. return { g: 0, c: null, s: '\\d{1,2}' };
  417. case 'L':
  418. return { g: 0, c: null, s: '(?:1|0)' };
  419. case 'Y':
  420. return { g: 1, c: 'y = parseInt(results[' + currentGroup + '], 10);\n', s: '(\\d{4})' };
  421. case 'y':
  422. return {
  423. g: 1,
  424. c:
  425. 'var ty = parseInt(results[' +
  426. currentGroup +
  427. '], 10);\n' +
  428. 'y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n',
  429. s: '(\\d{1,2})',
  430. };
  431. case 'a':
  432. return {
  433. g: 1,
  434. c:
  435. 'if (results[' +
  436. currentGroup +
  437. "] == 'am') {\n" +
  438. 'if (h == 12) { h = 0; }\n' +
  439. '} else { if (h < 12) { h += 12; }}',
  440. s: '(am|pm)',
  441. };
  442. case 'A':
  443. return {
  444. g: 1,
  445. c:
  446. 'if (results[' +
  447. currentGroup +
  448. "] == 'AM') {\n" +
  449. 'if (h == 12) { h = 0; }\n' +
  450. '} else { if (h < 12) { h += 12; }}',
  451. s: '(AM|PM)',
  452. };
  453. case 'g':
  454. case 'G':
  455. case 'h':
  456. case 'H':
  457. return { g: 1, c: 'h = parseInt(results[' + currentGroup + '], 10);\n', s: '(\\d{1,2})' };
  458. case 'i':
  459. return { g: 1, c: 'i = parseInt(results[' + currentGroup + '], 10);\n', s: '(\\d{2})' };
  460. case 's':
  461. return { g: 1, c: 's = parseInt(results[' + currentGroup + '], 10);\n', s: '(\\d{2})' };
  462. case 'X':
  463. return { g: 1, c: 'ms = parseInt(results[' + currentGroup + '], 10);\n', s: '(\\d{3})' };
  464. case 'O':
  465. case 'P':
  466. return {
  467. g: 1,
  468. c: 'z = Date.parseOffset(results[' + currentGroup + '], 10);\n',
  469. s: '(Z|[+-]\\d{2}:?\\d{2})',
  470. }; // "Z", "+05:00", "+0500" all acceptable.
  471. case 'T':
  472. return { g: 0, c: null, s: '[A-Z]{3}' };
  473. case 'Z':
  474. return { g: 1, c: 's = parseInt(results[' + currentGroup + '], 10);\n', s: '([+-]\\d{1,5})' };
  475. default:
  476. return { g: 0, c: null, s: String.escape(character) };
  477. }
  478. };
  479. Date.parseOffset = function (str) {
  480. if (str == 'Z') {
  481. return 0;
  482. } // UTC, no offset.
  483. var seconds;
  484. seconds = parseInt(str[0] + str[1] + str[2]) * 3600; // e.g., "+05" or "-08"
  485. if (str[3] == ':') {
  486. // "+HH:MM" is preferred iso8601 format ("O")
  487. seconds += parseInt(str[4] + str[5]) * 60;
  488. } else {
  489. // "+HHMM" is frequently used, though. ("P")
  490. seconds += parseInt(str[3] + str[4]) * 60;
  491. }
  492. return seconds;
  493. };
  494. Date.today = function () {
  495. var now = new Date();
  496. now.setHours(0);
  497. now.setMinutes(0);
  498. now.setSeconds(0);
  499. return now;
  500. };
  501. // convert the parsed date into UTC, but store the offset so we can optionally use it in dateFormat()
  502. Date.prototype.applyOffset = function (offset_seconds) {
  503. this.offset = offset_seconds * 1000;
  504. this.setTime(this.valueOf() + this.offset);
  505. return this;
  506. };
  507. Date.prototype.getTimezone = function () {
  508. return this.toString()
  509. .replace(/^.*? ([A-Z]{3}) [0-9]{4}.*$/, '$1')
  510. .replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, '$1$2$3')
  511. .replace(/^.*?[0-9]{4} \(([A-Z]{3})\)/, '$1');
  512. };
  513. Date.prototype.getGMTOffset = function () {
  514. return (
  515. (this.getTimezoneOffset() > 0 ? '-' : '+') +
  516. String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, '0') +
  517. String.leftPad(this.getTimezoneOffset() % 60, 2, '0')
  518. );
  519. };
  520. Date.prototype.getDayOfYear = function () {
  521. var num = 0;
  522. Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
  523. for (var i = 0; i < this.getMonth(); ++i) {
  524. num += Date.daysInMonth[i];
  525. }
  526. return num + this.getDate() - 1;
  527. };
  528. Date.prototype.getWeekOfYear = function () {
  529. // Skip to Thursday of this week
  530. var now = this.getDayOfYear() + (4 - this.getDay());
  531. // Find the first Thursday of the year
  532. var jan1 = new Date(this.getFullYear(), 0, 1);
  533. var then = 7 - jan1.getDay() + 4;
  534. document.write(then);
  535. return String.leftPad((now - then) / 7 + 1, 2, '0');
  536. };
  537. Date.prototype.isLeapYear = function () {
  538. var year = this.getFullYear();
  539. return (year & 3) == 0 && (year % 100 || (year % 400 == 0 && year));
  540. };
  541. Date.prototype.getFirstDayOfMonth = function () {
  542. var day = (this.getDay() - (this.getDate() - 1)) % 7;
  543. return day < 0 ? day + 7 : day;
  544. };
  545. Date.prototype.getLastDayOfMonth = function () {
  546. var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
  547. return day < 0 ? day + 7 : day;
  548. };
  549. Date.prototype.getDaysInMonth = function () {
  550. Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
  551. return Date.daysInMonth[this.getMonth()];
  552. };
  553. Date.prototype.getQuarter = function () {
  554. return Date.quarterFromMonthNum[this.getMonth()];
  555. };
  556. Date.prototype.getSuffix = function () {
  557. switch (this.getDate()) {
  558. case 1:
  559. case 21:
  560. case 31:
  561. return 'st';
  562. case 2:
  563. case 22:
  564. return 'nd';
  565. case 3:
  566. case 23:
  567. return 'rd';
  568. default:
  569. return 'th';
  570. }
  571. };
  572. String.escape = function (string) {
  573. return string.replace(/('|\\)/g, '\\$1');
  574. };
  575. String.leftPad = function (val, size, ch) {
  576. var result = new String(val);
  577. if (ch == null) {
  578. ch = ' ';
  579. }
  580. while (result.length < size) {
  581. result = ch + result;
  582. }
  583. return result;
  584. };
  585. Date.quarterFromMonthNum = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4];
  586. Date.daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  587. Date.monthNames = [
  588. 'January',
  589. 'February',
  590. 'March',
  591. 'April',
  592. 'May',
  593. 'June',
  594. 'July',
  595. 'August',
  596. 'September',
  597. 'October',
  598. 'November',
  599. 'December',
  600. ];
  601. Date.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  602. Date.y2kYear = 50;
  603. Date.monthNumbers = {
  604. Jan: 0,
  605. Feb: 1,
  606. Mar: 2,
  607. Apr: 3,
  608. May: 4,
  609. Jun: 5,
  610. Jul: 6,
  611. Aug: 7,
  612. Sep: 8,
  613. Oct: 9,
  614. Nov: 10,
  615. Dec: 11,
  616. };
  617. Date.patterns = {
  618. ISO8601LongPattern: 'Y\\-m\\-d\\TH\\:i\\:sO',
  619. ISO8601ShortPattern: 'Y\\-m\\-d',
  620. ShortDatePattern: 'n/j/Y',
  621. LongDatePattern: 'l, F d, Y',
  622. FullDateTimePattern: 'l, F d, Y g:i:s A',
  623. MonthDayPattern: 'F d',
  624. ShortTimePattern: 'g:i A',
  625. LongTimePattern: 'g:i:s A',
  626. SortableDateTimePattern: 'Y-m-d\\TH:i:s',
  627. UniversalSortableDateTimePattern: 'Y-m-d H:i:sO',
  628. YearMonthPattern: 'F, Y',
  629. };
  630. /**
  631. *
  632. * @author: Malishev Dmitry <dima.malishev@gmail.com>
  633. */
  634. var _DEBUG = true;
  635. var _DEBUG_LEVEL = 'ALL';
  636. // possible levels: ALL, IMPORTANT
  637. var Error = { FATAL: 1, WARNING: 0, NORMAL: -1 };
  638. /**
  639. * Init debug, grabs console object if accessible, or makes dummy debugger
  640. */
  641. var fb =
  642. _DEBUG && 'undefined' != typeof console
  643. ? console
  644. : {
  645. log: function () {},
  646. debug: function () {},
  647. info: function () {},
  648. warn: function () {},
  649. error: function () {},
  650. assert: function () {},
  651. dir: function () {},
  652. dirxml: function () {},
  653. trace: function () {},
  654. group: function () {},
  655. groupEnd: function () {},
  656. time: function () {},
  657. timeEnd: function () {},
  658. profile: function () {},
  659. profileEnd: function () {},
  660. count: function () {},
  661. msg: function () {},
  662. };
  663. var checked = false;
  664. var frmname = '';
  665. //
  666. var App = {
  667. // Main namespases for page specific functions
  668. // Core namespaces
  669. Ajax: {
  670. Busy: {},
  671. },
  672. Core: {},
  673. // CONSTANT VALUES
  674. Constants: {
  675. UNLIM_VALUE: 'unlimited', // overritten in i18n.js.php
  676. UNLIM_TRANSLATED_VALUE: 'unlimited', // overritten in i18n.js.php
  677. },
  678. // Actions. More widly used funcs
  679. Actions: {
  680. DB: {},
  681. WEB: {},
  682. PACKAGE: {},
  683. MAIL_ACC: {},
  684. MAIL: {},
  685. },
  686. // Utilities
  687. Helpers: {},
  688. HTML: {
  689. Build: {},
  690. },
  691. Filters: {},
  692. Env: {
  693. lang: GLOBAL.lang,
  694. },
  695. i18n: {},
  696. Listeners: {
  697. DB: {},
  698. WEB: {},
  699. PACKAGE: {},
  700. MAIL_ACC: {},
  701. },
  702. View: {
  703. HTML: {
  704. Build: {},
  705. },
  706. // pages related views
  707. },
  708. Cache: {
  709. clear: function () {}, // TODO: stub method, will be used later
  710. },
  711. Ref: {},
  712. Tmp: {},
  713. Thread: {
  714. run: function (delay, ref) {
  715. setTimeout(function () {
  716. ref();
  717. }, delay * 10);
  718. },
  719. },
  720. Settings: {
  721. GLOBAL: {},
  722. General: {},
  723. },
  724. Templates: {
  725. Templator: null,
  726. Tpl: {},
  727. _indexes: {},
  728. },
  729. };
  730. // Internals
  731. Array.prototype.set = function (key, value) {
  732. var index = this[0][key];
  733. this[1][index] = value;
  734. };
  735. Array.prototype.get = function (key) {
  736. var index = this[0][key];
  737. return this[1][index];
  738. };
  739. Array.prototype.finalize = function () {
  740. this.shift();
  741. this[0] = this[0].join('');
  742. return this[0];
  743. };
  744. Array.prototype.done = function () {
  745. return this.join('');
  746. };
  747. String.prototype.wrapperize = function (key, ns) {
  748. var tpl = App.Templates.get(key, ns);
  749. tpl.set(':content', this);
  750. return tpl.finalize();
  751. };
  752. App.Ajax.request = function (method, data, callback, onError) {
  753. // this will prevent multiple ajaxes on user clicks
  754. /*if (App.Helpers.isAjaxBusy(method, data)) {
  755. fb.warn('ajax request ['+method+'] is busy');
  756. return;
  757. }*/
  758. //App.Helpers.setAjaxBusy(method, data);
  759. data = data || {};
  760. var prgs = $('.progress-container');
  761. switch (method) {
  762. case 'cd':
  763. prgs.find('title').text('Opening dir');
  764. prgs.show();
  765. break;
  766. case 'delete_files':
  767. prgs.find('title').text('Deleting');
  768. prgs.show();
  769. break;
  770. case 'unpack_item':
  771. prgs.find('title').text('Unpacking');
  772. prgs.show();
  773. break;
  774. case 'create_file':
  775. prgs.find('title').text('Creating file');
  776. prgs.show();
  777. break;
  778. case 'create_dir':
  779. prgs.find('title').text('Creating directory');
  780. prgs.show();
  781. break;
  782. case 'rename_file':
  783. prgs.find('title').text('Renaming file');
  784. prgs.show();
  785. break;
  786. case 'copy_file':
  787. case 'copy_directory':
  788. prgs.find('title').text('Copying files');
  789. prgs.show();
  790. break;
  791. default:
  792. break;
  793. }
  794. jQuery.ajax({
  795. url: GLOBAL.ajax_url,
  796. global: false,
  797. type: data.request_method || 'GET',
  798. data: jQuery.extend(data, { action: method }),
  799. dataType: 'text boost',
  800. converters: {
  801. 'text boost': function (value) {
  802. value = value.trim();
  803. return $.parseJSON(value);
  804. },
  805. },
  806. async: true,
  807. cache: false,
  808. error: function (jqXHR, textStatus, errorThrown) {
  809. prgs.hide();
  810. onError && onError();
  811. if ('undefined' != typeof onError) {
  812. fb.error(textStatus);
  813. }
  814. },
  815. complete: function () {
  816. //App.Helpers.setAjaxFree(method, data);
  817. prgs.hide();
  818. },
  819. success: function (reply) {
  820. prgs.hide();
  821. //App.Helpers.setAjaxFree(method, data);
  822. try {
  823. callback && callback(reply);
  824. } catch (e) {
  825. fb.error('GENERAL ERROR with ajax method: ' + data.request_method + ' ' + e);
  826. //App.Helpers.generalError();
  827. }
  828. },
  829. });
  830. };
  831. jQuery.extend({
  832. keys: function (obj) {
  833. if (!obj) {
  834. return [];
  835. }
  836. var a = [];
  837. jQuery.each(obj, function (k) {
  838. a.push(k);
  839. });
  840. return a;
  841. },
  842. });
  843. App.Core.create_hidden_form = function (action) {
  844. var form = jQuery('<form>', {
  845. id: 'hidden-form',
  846. method: 'post',
  847. action: action,
  848. });
  849. jQuery('body').append(form);
  850. return form;
  851. };
  852. App.Core.extend_from_json = function (elm, data, prefix) {
  853. elm = jQuery(elm);
  854. var data = App.Core.flatten_json(data, prefix);
  855. var keys = jQuery.keys(data);
  856. for (var i = 0, cnt = keys.length; i < cnt; i++) {
  857. elm.append(
  858. jQuery('<input>', {
  859. name: keys[i],
  860. value: data[keys[i]],
  861. type: 'hidden',
  862. })
  863. );
  864. }
  865. return elm;
  866. };
  867. App.Core.flatten_json = function (data, prefix) {
  868. var keys = jQuery.keys(data);
  869. var result = {};
  870. prefix || (prefix = '');
  871. if (keys.length) {
  872. for (var i = 0, cnt = keys.length; i < cnt; i++) {
  873. var value = data[keys[i]];
  874. switch (typeof value) {
  875. case 'function':
  876. break;
  877. case 'object':
  878. result = jQuery.extend(
  879. result,
  880. App.Core.flatten_json(value, prefix + '[' + keys[i] + ']')
  881. );
  882. break;
  883. default:
  884. result[prefix + '[' + keys[i] + ']'] = value;
  885. }
  886. }
  887. return result;
  888. } else {
  889. return false;
  890. }
  891. };
  892. //
  893. // Cookies adapter
  894. // Allow to work old pages realisations of cookie requests
  895. //
  896. function createCookie(name, value, expire_days) {
  897. jQuery.cookie(name, value, { expires: expire_days });
  898. }
  899. function readCookie(name) {
  900. jQuery.cookie(name);
  901. }
  902. function eraseCookie(name) {
  903. jQuery.removeCookie(name);
  904. }
  905. /**
  906. * Timer for profiling
  907. */
  908. var timer = {};
  909. timer.start = function () {
  910. timer.start_time = new Date();
  911. };
  912. timer.stop = function (msg) {
  913. timer.stop_time = new Date();
  914. timer.print(msg);
  915. };
  916. timer.print = function (msg) {
  917. var passed = timer.stop_time - timer.start_time;
  918. fb.info(msg || '' + passed / 1000);
  919. };
  920. String.prototype.trim = function () {
  921. var str = this;
  922. str = str.replace(/^\s+/, '');
  923. for (var i = str.length - 1; i >= 0; i--) {
  924. if (/\S/.test(str.charAt(i))) {
  925. str = str.substring(0, i + 1);
  926. break;
  927. }
  928. }
  929. return str;
  930. };
  931. set_sticky_class = function () {
  932. var toolbar = $('.toolbar');
  933. var tableHeader = $('.table-header');
  934. var toolbarOffset = toolbar.offset().top;
  935. var headerHeight = $('.top-bar').outerHeight();
  936. if ($(window).scrollTop() > toolbarOffset - headerHeight) {
  937. toolbar.addClass('active');
  938. tableHeader.addClass('active');
  939. } else {
  940. toolbar.removeClass('active');
  941. tableHeader.removeClass('active');
  942. }
  943. };
  944. function checkedAll(frmname) {
  945. if ($('input#toggle-all').prop('checked')) {
  946. $('.l-unit:not(.header)').addClass('selected');
  947. $('.ch-toggle').prop('checked', true);
  948. $('.toggle-all').addClass('clicked-on');
  949. } else {
  950. $('.l-unit:not(.header)').removeClass('selected');
  951. $('.ch-toggle').prop('checked', false);
  952. $('.toggle-all').removeClass('clicked-on');
  953. }
  954. }
  955. function doSearch(url) {
  956. var url = url || '/search/';
  957. var loc = url + '?q=' + $('.js-search-input').val() + '&token=' + $('input[name="token"]').val();
  958. location.href = loc;
  959. return false;
  960. }
  961. function elementHideShow(elementToHideOrShow, trigger) {
  962. var el = document.getElementById(elementToHideOrShow);
  963. el.style.display = el.style.display === 'none' ? 'block' : 'none';
  964. if (typeof trigger !== 'undefined') {
  965. trigger.querySelector('.js-section-toggle-icon').classList.toggle('fa-square-minus');
  966. trigger.querySelector('.js-section-toggle-icon').classList.toggle('fa-square-plus');
  967. }
  968. }