PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/files/fuelux/2.6.6/scheduler.js

https://gitlab.com/Mirros/jsdelivr
JavaScript | 512 lines | 409 code | 72 blank | 31 comment | 76 complexity | d307c00fef2a5fb3378ab3300cf10090 MD5 | raw file
  1. /*
  2. * Fuel UX Scheduler
  3. * https://github.com/ExactTarget/fuelux
  4. *
  5. * Copyright (c) 2012 ExactTarget
  6. * Licensed under the MIT license.
  7. */
  8. define(['require','jquery','fuelux/combobox','fuelux/datepicker','fuelux/radio','fuelux/select','fuelux/spinner'],function(require) {
  9. var $ = require('jquery');
  10. var old = $.fn.scheduler;
  11. require('fuelux/combobox');
  12. require('fuelux/datepicker');
  13. require('fuelux/radio');
  14. require('fuelux/select');
  15. require('fuelux/spinner');
  16. // SCHEDULER CONSTRUCTOR AND PROTOTYPE
  17. var Scheduler = function (element, options) {
  18. var self = this;
  19. this.$element = $(element);
  20. this.options = $.extend({}, $.fn.scheduler.defaults, options);
  21. // cache elements
  22. this.$startDate = this.$element.find('.scheduler-start .datepicker');
  23. this.$startTime = this.$element.find('.scheduler-start .combobox');
  24. this.$timeZone = this.$element.find('.scheduler-timezone .select');
  25. this.$repeatIntervalPanel = this.$element.find('.repeat-interval-panel');
  26. this.$repeatIntervalSelect = this.$element.find('.repeat-interval .select');
  27. this.$repeatIntervalSpinner = this.$element.find('.repeat-interval-panel .spinner');
  28. this.$repeatIntervalTxt = this.$element.find('.repeat-interval-text');
  29. this.$end = this.$element.find('.scheduler-end');
  30. this.$endAfter = this.$end.find('.spinner');
  31. this.$endSelect= this.$end.find('.select');
  32. this.$endDate = this.$end.find('.datepicker');
  33. // panels
  34. this.$recurrencePanels = this.$element.find('.recurrence-panel');
  35. // bind events
  36. this.$element.find('.scheduler-weekly .btn-group .btn').on('click', function(e, data){ self.changed(e, data, true); });
  37. this.$element.find('.combobox').on('changed', $.proxy(this.changed, this));
  38. this.$element.find('.datepicker').on('changed', $.proxy(this.changed, this));
  39. this.$element.find('.select').on('changed', $.proxy(this.changed, this));
  40. this.$element.find('.spinner').on('changed', $.proxy(this.changed, this));
  41. this.$element.find('.scheduler-monthly label.radio, .scheduler-yearly label.radio').on('mouseup', $.proxy(this.changed, this));
  42. this.$repeatIntervalSelect.on('changed', $.proxy(this.repeatIntervalSelectChanged, this));
  43. this.$endSelect.on('changed', $.proxy(this.endSelectChanged, this));
  44. //initialize sub-controls
  45. this.$startDate.datepicker();
  46. this.$startTime.combobox();
  47. if(this.$startTime.find('input').val()===''){
  48. this.$startTime.combobox('selectByIndex', 0);
  49. }
  50. this.$repeatIntervalSpinner.spinner();
  51. this.$endAfter.spinner();
  52. this.$endDate.datepicker();
  53. };
  54. Scheduler.prototype = {
  55. constructor: Scheduler,
  56. changed: function(e, data, propagate){
  57. if(!propagate){
  58. e.stopPropagation();
  59. }
  60. this.$element.trigger('changed', {
  61. data: (data!==undefined) ? data : $(e.currentTarget).data(),
  62. originalEvent: e,
  63. value: this.getValue()
  64. });
  65. },
  66. disable: function(){
  67. this.toggleState('disable');
  68. },
  69. enable: function(){
  70. this.toggleState('enable');
  71. },
  72. // called when the end range changes
  73. // (Never, After, On date)
  74. endSelectChanged: function(e, data) {
  75. var selectedItem, val;
  76. if(!data){
  77. selectedItem = this.$endSelect.select('selectedItem');
  78. val = selectedItem.value;
  79. }else{
  80. val = data.value;
  81. }
  82. // hide all panels
  83. this.$endAfter.hide();
  84. this.$endDate.hide();
  85. if(val==='after'){
  86. this.$endAfter.show();
  87. }else if(val==='date'){
  88. this.$endDate.show();
  89. }
  90. },
  91. getValue: function(){
  92. // FREQ = frequency (hourly, daily, monthly...)
  93. // BYDAY = when picking days (MO,TU,WE,etc)
  94. // BYMONTH = when picking months (Jan,Feb,March) - note the values should be 1,2,3...
  95. // BYMONTHDAY = when picking days of the month (1,2,3...)
  96. // BYSETPOS = when picking First,Second,Third,Fourth,Last (1,2,3,4,-1)
  97. var interval = this.$repeatIntervalSpinner.spinner('value');
  98. var pattern = '';
  99. var repeat = this.$repeatIntervalSelect.select('selectedItem').value;
  100. var startTime = this.$startTime.combobox('selectedItem').text.toLowerCase();
  101. var timeZone = this.$timeZone.select('selectedItem');
  102. var getFormattedDate = function(dateObj, dash){
  103. var fdate = '';
  104. var item;
  105. fdate += dateObj.getFullYear();
  106. fdate += dash;
  107. item = dateObj.getMonth() + 1; //because 0 indexing makes sense when dealing with months /sarcasm
  108. fdate += (item<10) ? '0' + item : item;
  109. fdate += dash;
  110. item = dateObj.getDate();
  111. fdate += (item<10) ? '0' + item : item;
  112. return fdate;
  113. };
  114. var day, days, hasAm, hasPm, month, pos, startDateTime, type;
  115. startDateTime = '' + getFormattedDate(this.$startDate.datepicker('getDate'), '-');
  116. startDateTime += 'T';
  117. hasAm = (startTime.search('am')>=0);
  118. hasPm = (startTime.search('pm')>=0);
  119. startTime = $.trim(startTime.replace(/am/g, '').replace(/pm/g, '')).split(':');
  120. startTime[0] = parseInt(startTime[0], 10);
  121. startTime[1] = parseInt(startTime[1], 10);
  122. if(hasAm && startTime[0]>11){
  123. startTime[0] = 0;
  124. }else if(hasPm && startTime[0]<12){
  125. startTime[0] += 12;
  126. }
  127. startDateTime += (startTime[0]<10) ? '0' + startTime[0] : startTime[0];
  128. startDateTime += ':';
  129. startDateTime += (startTime[1]<10) ? '0' + startTime[1] : startTime[1];
  130. startDateTime += (timeZone.offset==='+00:00') ? 'Z' : timeZone.offset;
  131. if(repeat === 'none') {
  132. pattern = 'FREQ=DAILY;INTERVAL=1;COUNT=1;';
  133. }
  134. else if(repeat === 'hourly') {
  135. pattern = 'FREQ=HOURLY;';
  136. pattern += 'INTERVAL=' + interval + ';';
  137. }
  138. else if(repeat === 'daily') {
  139. pattern += 'FREQ=DAILY;';
  140. pattern += 'INTERVAL=' + interval + ';';
  141. }
  142. else if(repeat === 'weekdays') {
  143. pattern += 'FREQ=DAILY;';
  144. pattern += 'BYDAY=MO,TU,WE,TH,FR;';
  145. pattern += 'INTERVAL=1;';
  146. }
  147. else if(repeat === 'weekly') {
  148. days = [];
  149. this.$element.find('.scheduler-weekly .btn-group button.active').each(function() {
  150. days.push($(this).data().value);
  151. });
  152. pattern += 'FREQ=WEEKLY;';
  153. pattern += 'BYDAY=' + days.join(',') + ';';
  154. pattern += 'INTERVAL=' + interval + ';';
  155. }
  156. else if(repeat === 'monthly') {
  157. pattern += 'FREQ=MONTHLY;';
  158. pattern += 'INTERVAL=' + interval + ';';
  159. type = parseInt(this.$element.find('input[name=scheduler-month]:checked').val(), 10);
  160. if(type === 1) {
  161. day = parseInt(this.$element.find('.scheduler-monthly-date .select').select('selectedItem').text, 10);
  162. pattern += 'BYMONTHDAY=' + day + ';';
  163. }
  164. else if(type === 2) {
  165. days = this.$element.find('.month-days').select('selectedItem').value;
  166. pos = this.$element.find('.month-day-pos').select('selectedItem').value;
  167. pattern += 'BYDAY=' + days + ';';
  168. pattern += 'BYSETPOS=' + pos + ';';
  169. }
  170. }
  171. else if(repeat === 'yearly') {
  172. pattern += 'FREQ=YEARLY;';
  173. type = parseInt(this.$element.find('input[name=scheduler-year]:checked').val(), 10);
  174. if(type === 1) {
  175. month = this.$element.find('.scheduler-yearly-date .year-month').select('selectedItem').value;
  176. day = this.$element.find('.year-month-day').select('selectedItem').text;
  177. pattern += 'BYMONTH=' + month + ';';
  178. pattern += 'BYMONTHDAY=' + day + ';';
  179. }
  180. else if(type === 2) {
  181. days = this.$element.find('.year-month-days').select('selectedItem').value;
  182. pos = this.$element.find('.year-month-day-pos').select('selectedItem').value;
  183. month = this.$element.find('.scheduler-yearly-day .year-month').select('selectedItem').value;
  184. pattern += 'BYDAY=' + days + ';';
  185. pattern += 'BYSETPOS=' + pos + ';';
  186. pattern += 'BYMONTH=' + month + ';';
  187. }
  188. }
  189. var end = this.$endSelect.select('selectedItem').value;
  190. var duration = '';
  191. // if both UNTIL and COUNT are not specified, the recurrence will repeat forever
  192. // http://tools.ietf.org/html/rfc2445#section-4.3.10
  193. if(repeat !=='none'){
  194. if(end === 'after') {
  195. duration = 'COUNT=' + this.$endAfter.spinner('value') + ';';
  196. }
  197. else if(end === 'date') {
  198. duration = 'UNTIL=' + getFormattedDate(this.$endDate.datepicker('getDate'), '') + ';';
  199. }
  200. }
  201. pattern += duration;
  202. var data = {
  203. startDateTime: startDateTime,
  204. timeZone: {
  205. name: timeZone.name,
  206. offset: timeZone.offset
  207. },
  208. recurrencePattern: pattern
  209. };
  210. return data;
  211. },
  212. // called when the repeat interval changes
  213. // (None, Hourly, Daily, Weekdays, Weekly, Monthly, Yearly
  214. repeatIntervalSelectChanged: function(e, data) {
  215. var selectedItem, val, txt;
  216. if(!data){
  217. selectedItem = this.$repeatIntervalSelect.select('selectedItem');
  218. val = selectedItem.value;
  219. txt = selectedItem.text;
  220. }else{
  221. val = data.value;
  222. txt = data.text;
  223. }
  224. // set the text
  225. this.$repeatIntervalTxt.text(txt);
  226. switch(val.toLowerCase()) {
  227. case 'hourly':
  228. case 'daily':
  229. case 'weekly':
  230. case 'monthly':
  231. this.$repeatIntervalPanel.show();
  232. break;
  233. default:
  234. this.$repeatIntervalPanel.hide();
  235. break;
  236. }
  237. // hide all panels
  238. this.$recurrencePanels.hide();
  239. // show panel for current selection
  240. this.$element.find('.scheduler-' + val).show();
  241. // the end selection should only be shown when
  242. // the repeat interval is not "None (run once)"
  243. if(val === 'none') {
  244. this.$end.hide();
  245. }
  246. else {
  247. this.$end.show();
  248. }
  249. },
  250. setValue: function(options){
  251. var hours, i, item, l, minutes, period, recur, temp;
  252. if(options.startDateTime){
  253. temp = options.startDateTime.split('T');
  254. this.$startDate.datepicker('setDate', temp[0]);
  255. if(temp[1]){
  256. temp[1] = temp[1].split(':');
  257. hours = parseInt(temp[1][0], 10);
  258. minutes = (temp[1][1]) ? parseInt(temp[1][1].split('+')[0].split('-')[0].split('Z')[0], 10) : 0;
  259. period = (hours<12) ? 'AM' : 'PM';
  260. if(hours===0){
  261. hours = 12;
  262. }else if(hours>12){
  263. hours -= 12;
  264. }
  265. minutes = (minutes<10) ? '0' + minutes : minutes;
  266. temp = hours + ':' + minutes + ' ' + period;
  267. this.$startTime.find('input').val(temp);
  268. this.$startTime.combobox('selectByText', temp);
  269. }
  270. }
  271. item = 'li[data';
  272. if(options.timeZone){
  273. if(typeof(options.timeZone)==='string'){
  274. item += '-name="' + options.timeZone;
  275. }else{
  276. if(options.timeZone.name){
  277. item += '-name="' + options.timeZone.name;
  278. }else{
  279. item += '-offset="' + options.timeZone.offset;
  280. }
  281. }
  282. item += '"]';
  283. this.$timeZone.select('selectBySelector', item);
  284. }else if(options.startDateTime){
  285. temp = options.startDateTime.split('T')[1];
  286. if(temp){
  287. if(temp.search(/\+/)>-1){
  288. temp = '+' + $.trim(temp.split('+')[1]);
  289. }else if(temp.search(/\-/)>-1){
  290. temp = '-' + $.trim(temp.split('-')[1]);
  291. }else{
  292. temp = '+00:00';
  293. }
  294. }else{
  295. temp = '+00:00';
  296. }
  297. item += '-offset="' + temp + '"]';
  298. this.$timeZone.select('selectBySelector', item);
  299. }
  300. if(options.recurrencePattern){
  301. recur = {};
  302. temp = options.recurrencePattern.toUpperCase().split(';');
  303. for(i=0, l=temp.length; i<l; i++){
  304. if(temp[i]!==''){
  305. item = temp[i].split('=');
  306. recur[item[0]] = item[1];
  307. }
  308. }
  309. if(recur.FREQ==='DAILY'){
  310. if(recur.BYDAY==='MO,TU,WE,TH,FR'){
  311. item = 'weekdays';
  312. }else{
  313. if(recur.INTERVAL==='1' && recur.COUNT==='1'){
  314. item = 'none';
  315. }else{
  316. item = 'daily';
  317. }
  318. }
  319. }else if(recur.FREQ==='HOURLY'){
  320. item = 'hourly';
  321. }else if(recur.FREQ==='WEEKLY'){
  322. if(recur.BYDAY){
  323. item = this.$element.find('.scheduler-weekly .btn-group');
  324. item.find('button').removeClass('active');
  325. temp = recur.BYDAY.split(',');
  326. for(i=0,l=temp.length; i<l; i++){
  327. item.find('button[data-value="' + temp[i] + '"]').addClass('active');
  328. }
  329. }
  330. item = 'weekly';
  331. }else if(recur.FREQ==='MONTHLY'){
  332. this.$element.find('.scheduler-monthly input').removeClass('checked');
  333. if(recur.BYMONTHDAY){
  334. temp = this.$element.find('.scheduler-monthly-date');
  335. temp.find('input').addClass('checked');
  336. temp.find('.select').select('selectByValue', recur.BYMONTHDAY);
  337. }else if(recur.BYDAY){
  338. temp = this.$element.find('.scheduler-monthly-day');
  339. temp.find('input').addClass('checked');
  340. if(recur.BYSETPOS){
  341. temp.find('.month-day-pos').select('selectByValue', recur.BYSETPOS);
  342. }
  343. temp.find('.month-days').select('selectByValue', recur.BYDAY);
  344. }
  345. item = 'monthly';
  346. }else if(recur.FREQ==='YEARLY'){
  347. this.$element.find('.scheduler-yearly input').removeClass('checked');
  348. if(recur.BYMONTHDAY){
  349. temp = this.$element.find('.scheduler-yearly-date');
  350. temp.find('input').addClass('checked');
  351. if(recur.BYMONTH){
  352. temp.find('.year-month').select('selectByValue', recur.BYMONTH);
  353. }
  354. temp.find('.year-month-day').select('selectByValue', recur.BYMONTHDAY);
  355. }else if(recur.BYSETPOS){
  356. temp = this.$element.find('.scheduler-yearly-day');
  357. temp.find('input').addClass('checked');
  358. temp.find('.year-month-day-pos').select('selectByValue', recur.BYSETPOS);
  359. if(recur.BYDAY){
  360. temp.find('.year-month-days').select('selectByValue', recur.BYDAY);
  361. }
  362. if(recur.BYMONTH){
  363. temp.find('.year-month').select('selectByValue', recur.BYMONTH);
  364. }
  365. }
  366. item = 'yearly';
  367. }else{
  368. item = 'none';
  369. }
  370. if(recur.COUNT){
  371. this.$endAfter.spinner('value', parseInt(recur.COUNT, 10));
  372. this.$endSelect.select('selectByValue', 'after');
  373. }else if(recur.UNTIL){
  374. temp = recur.UNTIL;
  375. if(temp.length===8){
  376. temp = temp.split('');
  377. temp.splice(4, 0, '-');
  378. temp.splice(7, 0, '-');
  379. temp = temp.join('');
  380. }
  381. this.$endDate.datepicker('setDate', temp);
  382. this.$endSelect.select('selectByValue', 'date');
  383. }
  384. this.endSelectChanged();
  385. if(recur.INTERVAL){
  386. this.$repeatIntervalSpinner.spinner('value', parseInt(recur.INTERVAL, 10));
  387. }
  388. this.$repeatIntervalSelect.select('selectByValue', item);
  389. this.repeatIntervalSelectChanged();
  390. }
  391. },
  392. toggleState: function(action){
  393. this.$element.find('.combobox').combobox(action);
  394. this.$element.find('.datepicker').datepicker(action);
  395. this.$element.find('.select').select(action);
  396. this.$element.find('.spinner').spinner(action);
  397. this.$element.find('.radio').radio(action);
  398. if(action==='disable'){
  399. action = 'addClass';
  400. }else{
  401. action = 'removeClass';
  402. }
  403. this.$element.find('.scheduler-weekly .btn-group')[action]('disabled');
  404. },
  405. value: function(options) {
  406. if(options){
  407. return this.setValue(options);
  408. }else{
  409. return this.getValue();
  410. }
  411. }
  412. };
  413. // SCHEDULER PLUGIN DEFINITION
  414. $.fn.scheduler = function (option) {
  415. var args = Array.prototype.slice.call( arguments, 1 );
  416. var methodReturn;
  417. var $set = this.each(function () {
  418. var $this = $(this);
  419. var data = $this.data('scheduler');
  420. var options = typeof option === 'object' && option;
  421. if (!data) $this.data('scheduler', (data = new Scheduler(this, options)));
  422. if( typeof option === 'string' ) methodReturn = data[ option ].apply( data, args );
  423. });
  424. return ( methodReturn === undefined ) ? $set : methodReturn;
  425. };
  426. $.fn.scheduler.defaults = {};
  427. $.fn.scheduler.Constructor = Scheduler;
  428. $.fn.scheduler.noConflict = function () {
  429. $.fn.scheduler = old;
  430. return this;
  431. };
  432. // SCHEDULER DATA-API
  433. $(function () {
  434. $('body').on('mousedown.scheduler.data-api', '.scheduler', function () {
  435. var $this = $(this);
  436. if ($this.data('scheduler')) return;
  437. $this.scheduler($this.data());
  438. });
  439. });
  440. });