1/* 2 * # Semantic UI 0.0.6
vendor: 12,234 bytes, lines 2-299
2 - Calendar 3 * http://github.com/semantic-org/semantic-ui/ 4 * 5 * 6 * Released under the MIT license 7 * http://opensource.org/licenses/MIT 8 */ 9 10; 11(function ($, window, document, undefined) { 12 13 "use strict"; 14 15 window = (typeof window != 'undefined' && window.Math == Math) 16 ? window 17 : (typeof self != 'undefined' && self.Math == Math) 18 ? self 19 : Function('return this')() 20 ; 21 22 $.fn.calendar = function (parameters) { 23 24 var 25 $allModules = $(this), 26 27 moduleSelector = $allModules.selector || '', 28 29 time = new Date().getTime(), 30 performance = [], 31 32 query = arguments[0], 33 methodInvoked = (typeof query == 'string'), 34 queryArguments = [].slice.call(arguments, 1), 35 returnedValue 36 ; 37 38 $allModules 39 .each(function () { 40 var 41 settings = ( $.isPlainObject(parameters) ) 42 ? $.extend(true, {}, $.fn.calendar.settings, parameters) 43 : $.extend({}, $.fn.calendar.settings), 44 45 className = settings.className, 46 namespace = settings.namespace, 47 selector = settings.selector, 48 formatter = settings.formatter, 49 parser = settings.parser, 50 metadata = settings.metadata, 51 error = settings.error, 52 53 eventNamespace = '.' + namespace, 54 moduleNamespace = 'module-' + namespace, 55 56 $module = $(this), 57 $input = $module.find(selector.input), 58 $container = $module.find(selector.popup), 59 $activator = $module.find(selector.activator), 60 61 element = this, 62 instance = $module.data(moduleNamespace), 63 64 isTouch, 65 isTouchDown = false, 66 focusDateUsedForRange = false, 67 module 68 ; 69 70 module = { 71 72 initialize: function () { 73 module.debug('Initializing calendar for', element); 74 75 isTouch = module.get.isTouch(); 76 module.setup.popup(); 77 module.setup.inline(); 78 module.setup.input(); 79 module.setup.date(); 80 module.create.calendar(); 81 82 module.bind.events(); 83 module.instantiate(); 84 }, 85 86 instantiate: function () { 87 module.verbose('Storing instance of calendar'); 88 instance = module; 89 $module.data(moduleNamespace, instance); 90 }, 91 92 destroy: function () { 93 module.verbose('Destroying previous calendar for', element); 94 $module.removeData(moduleNamespace); 95 module.unbind.events(); 96 }, 97 98 setup: { 99 popup: function () { 100 if (settings.inline) { 101 return; 102 } 103 if (!$activator.length) { 104 $activator = $module.children().first(); 105 if (!$activator.length) { 106 return; 107 } 108 } 109 if ($.fn.popup === undefined) { 110 module.error(error.popup); 111 return; 112 } 113 if (!$container.length) { 114 //prepend the popup element to the activator's parent so that it has less chance of messing with 115 //the styling (eg input action button needs to be the last child to have correct border radius) 116 $container = $('<div/>').addClass(className.popup).prependTo($activator.parent()); 117 } 118 $container.addClass(className.calendar); 119 var onVisible = settings.onVisible; 120 var onHidden = settings.onHidden; 121 if (!$input.length) { 122 //no input, $container has to handle focus/blur 123 $container.attr('tabindex', '0'); 124 onVisible = function () { 125 module.focus(); 126 return settings.onVisible.apply($container, arguments); 127 }; 128 onHidden = function () { 129 module.blur(); 130 return settings.onHidden.apply($container, arguments); 131 }; 132 } 133 var onShow = function () { 134 //reset the focus date onShow 135 module.set.focusDate(module.get.date()); 136 module.set.mode(settings.startMode); 137 return settings.onShow.apply($container, arguments); 138 }; 139 var on = settings.on || ($input.length ? 'focus' : 'click'); 140 var options = $.extend({}, settings.popupOptions, { 141 popup: $container, 142 on: on, 143 hoverable: on === 'hover', 144 onShow: onShow, 145 onVisible: onVisible, 146 onHide: settings.onHide, 147 onHidden: onHidden 148 }); 149 module.popup(options); 150 }, 151 inline: function () { 152 if ($activator.length && !settings.inline) { 153 return; 154 } 155 $container = $('<div/>').addClass(className.calendar).appendTo($module); 156 if (!$input.length) { 157 $container.attr('tabindex', '0'); 158 } 159 }, 160 input: function () { 161 if (settings.touchReadonly && $input.length && isTouch) { 162 $input.prop('readonly', true); 163 } 164 }, 165 date: function () { 166 if ($input.length) { 167 var val = $input.val(); 168 var date = parser.date(val, settings); 169 module.set.date(date, settings.formatInput, false); 170 } 171 } 172 }, 173 174 create: { 175 calendar: function () { 176 var i, r, c, p, row, cell, pageGrid; 177 178 var mode = module.get.mode(); 179 var today = new Date(); 180 var date = module.get.date(); 181 var focusDate = module.get.focusDate(); 182 var display = focusDate || date || settings.initialDate || today; 183 display = module.helper.dateInRange(display); 184 185 if (!focusDate) { 186 focusDate = display; 187 module.set.focusDate(focusDate, false, false); 188 } 189 190 var isYear = mode === 'year'; 191 var isMonth = mode === 'month'; 192 var isDay = mode === 'day'; 193 var isHour = mode === 'hour'; 194 var isMinute = mode === 'minute'; 195 var isTimeOnly = settings.type === 'time'; 196 197 var multiMonth = Math.max(settings.multiMonth, 1); 198 var monthOffset = !isDay ? 0 : module.get.monthOffset(); 199 200 var minute = display.getMinutes(); 201 var hour = display.getHours(); 202 var day = display.getDate(); 203 var startMonth = display.getMonth() + monthOffset; 204 var year = display.getFullYear(); 205 206 var columns = isDay ? 7 : isHour ? 4 : 3; 207 var columnsString = columns === 7 ? 'seven' : columns === 4 ? 'four' : 'three'; 208 var rows = isDay || isHour ? 6 : 4; 209 var pages = isDay ? multiMonth : 1; 210 211 var container = $container; 212 container.empty(); 213 if (pages > 1) { 214 pageGrid = $('<div/>').addClass(className.grid).appendTo(container); 215 } 216 217 for (p = 0; p < pages; p++) { 218 if (pages > 1) { 219 var pageColumn = $('<div/>').addClass(className.column).appendTo(pageGrid); 220 container = pageColumn; 221 } 222 223 var month = startMonth + p; 224 var firstMonthDayColumn = (new Date(year, month, 1).getDay() - settings.firstDayOfWeek % 7 + 7) % 7; 225 if (!settings.constantHeight && isDay) { 226 var requiredCells = new Date(year, month + 1, 0).getDate() + firstMonthDayColumn; 227 rows = Math.ceil(requiredCells / 7); 228 } 229 230 var yearChange = isYear ? 10 : isMonth ? 1 : 0; 231 var monthChange = isDay ? 1 : 0; 232 var dayChange = isHour || isMinute ? 1 : 0; 233 var prevNextDay = isHour || isMinute ? day : 1; 234 var prevDate = new Date(year - yearChange, month - monthChange, prevNextDay - dayChange, hour); 235 var nextDate = new Date(year + yearChange, month + monthChange, prevNextDay + dayChange, hour); 236 237 var prevLast = isYear ? new Date(Math.ceil(year / 10) * 10 - 9, 0, 0) : 238 isMonth ? new Date(year, 0, 0) : isDay ? new Date(year, month, 0) : new Date(year, month, day, -1); 239 var nextFirst = isYear ? new Date(Math.ceil(year / 10) * 10 + 1, 0, 1) : 240 isMonth ? new Date(year + 1, 0, 1) : isDay ? new Date(year, month + 1, 1) : new Date(year, month, day + 1); 241 242 var table = $('<table/>').addClass(className.table).addClass(columnsString + ' column').addClass(mode).appendTo(container); 243 244 //no header for time-only mode 245 if (!isTimeOnly) { 246 var thead = $('<thead/>').appendTo(table); 247 248 row = $('<tr/>').appendTo(thead); 249 cell = $('<th/>').attr('colspan', '' + columns).appendTo(row); 250 251 var headerDate = isYear || isMonth ? new Date(year, 0, 1) : 252 isDay ? new Date(year, month, 1) : new Date(year, month, day, hour, minute); 253 var headerText = $('<span/>').addClass(className.link).appendTo(cell); 254 headerText.text(formatter.header(headerDate, mode, settings)); 255 var newMode = isMonth ? (settings.disableYear ? 'day' : 'year') : 256 isDay ? (settings.disableMonth ? 'year' : 'month') : 'day'; 257 headerText.data(metadata.mode, newMode); 258 259 if (p === 0) { 260 var prev = $('<span/>').addClass(className.prev).appendTo(cell); 261 prev.data(metadata.focusDate, prevDate); 262 prev.toggleClass(className.disabledCell, !module.helper.isDateInRange(prevLast, mode)); 263 $('<i/>').addClass(className.prevIcon).appendTo(prev); 264 } 265 266 if (p === pages - 1) { 267 var next = $('<span/>').addClass(className.next).appendTo(cell); 268 next.data(metadata.focusDate, nextDate); 269 next.toggleClass(className.disabledCell, !module.helper.isDateInRange(nextFirst, mode)); 270 $('<i/>').addClass(className.nextIcon).appendTo(next); 271 } 272 273 if (isDay) { 274 row = $('<tr/>').appendTo(thead); 275 for (i = 0; i < columns; i++) { 276 cell = $('<th/>').appendTo(row); 277 cell.text(formatter.dayColumnHeader((i + settings.firstDayOfWeek) % 7, settings)); 278 } 279 } 280 } 281 282 var tbody = $('<tbody/>').appendTo(table); 283 i = isYear ? Math.ceil(year / 10) * 10 - 9 : isDay ? 1 - firstMonthDayColumn : 0; 284 for (r = 0; r < rows; r++) { 285 row = $('<tr/>').appendTo(tbody); 286 for (c = 0; c < columns; c++, i++) { 287 var cellDate = isYear ? new Date(i, month, 1, hour, minute) : 288 isMonth ? new Date(year, i, 1, hour, minute) : isDay ? new Date(year, month, i, hour, minute) : 289 isHour ? new Date(year, month, day, i) : new Date(year, month, day, hour, i * 5); 290 var cellText = isYear ? i : 291 isMonth ? settings.text.monthsShort[i] : isDay ? cellDate.getDate() : 292 formatter.time(cellDate, settings, true); 293 cell = $('<td/>').addClass(className.cell).appendTo(row); 294 cell.text(cellText); 295 cell.data(metadata.date, cellDate); 296 var adjacent = isDay && cellDate.getMonth() !== ((month + 12) % 12); 297 var disabled = adjacent || !module.helper.isDateInRange(cellDate, mode) || settings.isDisabled(cellDate, mode); 298 var active = module.helper.dateEqual(cellDate, date, mode); 299
299cell.toggleClass(className.adjacentCell, adjacent); 300 cell.toggleClass(className.disabledCell, disabled); 301 cell.toggleClass(className.activeCell, active && !adjacent); 302 if (!isHour && !isMinute) { 303 cell.toggleClass(className.todayCell, !adjacent && module.helper.dateEqual(cellDate, today, mode)); 304 }
vendor: 40,370 bytes, lines 304-1364
304 305 if (module.helper.dateEqual(cellDate, focusDate, mode)) { 306 //ensure that the focus date is exactly equal to the cell date 307 //so that, if selected, the correct value is set 308 module.set.focusDate(cellDate, false, false); 309 } 310 } 311 } 312 313 if (settings.today) { 314 var todayRow = $('<tr/>').appendTo(tbody); 315 var todayButton = $('<td/>').attr('colspan', '' + columns).addClass(className.today).appendTo(todayRow); 316 todayButton.text(formatter.today(settings)); 317 todayButton.data(metadata.date, today); 318 } 319 320 module.update.focus(false, table); 321 } 322 } 323 }, 324 325 update: { 326 focus: function (updateRange, container) { 327 container = container || $container; 328 var mode = module.get.mode(); 329 var date = module.get.date(); 330 var focusDate = module.get.focusDate(); 331 var startDate = module.get.startDate(); 332 var endDate = module.get.endDate(); 333 var rangeDate = (updateRange ? focusDate : null) || date || (!isTouch ? focusDate : null); 334 335 container.find('td').each(function () { 336 var cell = $(this); 337 var cellDate = cell.data(metadata.date); 338 if (!cellDate) { 339 return; 340 } 341 var disabled = cell.hasClass(className.disabledCell); 342 var active = cell.hasClass(className.activeCell); 343 var adjacent = cell.hasClass(className.adjacentCell); 344 var focused = module.helper.dateEqual(cellDate, focusDate, mode); 345 var inRange = !rangeDate ? false : 346 ((!!startDate && module.helper.isDateInRange(cellDate, mode, startDate, rangeDate)) || 347 (!!endDate && module.helper.isDateInRange(cellDate, mode, rangeDate, endDate))); 348 cell.toggleClass(className.focusCell, focused && (!isTouch || isTouchDown) && !adjacent); 349 cell.toggleClass(className.rangeCell, inRange && !active && !disabled); 350 }); 351 } 352 }, 353 354 refresh: function () { 355 module.create.calendar(); 356 }, 357 358 bind: { 359 events: function () { 360 $container.on('mousedown' + eventNamespace, module.event.mousedown); 361 $container.on('touchstart' + eventNamespace, module.event.mousedown); 362 $container.on('mouseup' + eventNamespace, module.event.mouseup); 363 $container.on('touchend' + eventNamespace, module.event.mouseup); 364 $container.on('mouseover' + eventNamespace, module.event.mouseover); 365 if ($input.length) { 366 $input.on('input' + eventNamespace, module.event.inputChange); 367 $input.on('focus' + eventNamespace, module.event.inputFocus); 368 $input.on('blur' + eventNamespace, module.event.inputBlur); 369 $input.on('click' + eventNamespace, module.event.inputClick); 370 $input.on('keydown' + eventNamespace, module.event.keydown); 371 } else { 372 $container.on('keydown' + eventNamespace, module.event.keydown); 373 } 374 } 375 }, 376 377 unbind: { 378 events: function () { 379 $container.off(eventNamespace); 380 if ($input.length) { 381 $input.off(eventNamespace); 382 } 383 } 384 }, 385 386 event: { 387 mouseover: function (event) { 388 var target = $(event.target); 389 var date = target.data(metadata.date); 390 var mousedown = event.buttons === 1; 391 if (date) { 392 module.set.focusDate(date, false, true, mousedown); 393 } 394 }, 395 mousedown: function (event) { 396 if ($input.length) { 397 //prevent the mousedown on the calendar causing the input to lose focus 398 event.preventDefault(); 399 } 400 isTouchDown = event.type.indexOf('touch') >= 0; 401 var target = $(event.target); 402 var date = target.data(metadata.date); 403 if (date) { 404 module.set.focusDate(date, false, true, true); 405 } 406 }, 407 mouseup: function (event) { 408 //ensure input has focus so that it receives keydown events for calendar navigation 409 module.focus(); 410 event.preventDefault(); 411 event.stopPropagation(); 412 isTouchDown = false; 413 var target = $(event.target); 414 var parent = target.parent(); 415 if (parent.data(metadata.date) || parent.data(metadata.focusDate) || parent.data(metadata.mode)) { 416 //clicked on a child element, switch to parent (used when clicking directly on prev/next <i> icon element) 417 target = parent; 418 } 419 var date = target.data(metadata.date); 420 var focusDate = target.data(metadata.focusDate); 421 var mode = target.data(metadata.mode); 422 if (date) { 423 var forceSet = target.hasClass(className.today); 424 module.selectDate(date, forceSet); 425 } 426 else if (focusDate) { 427 module.set.focusDate(focusDate); 428 } 429 else if (mode) { 430 module.set.mode(mode); 431 } 432 }, 433 keydown: function (event) { 434 if (event.keyCode === 27 || event.keyCode === 9) { 435 //esc || tab 436 module.popup('hide'); 437 } 438 439 if (module.popup('is visible')) { 440 if (event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40) { 441 //arrow keys 442 var mode = module.get.mode(); 443 var bigIncrement = mode === 'day' ? 7 : mode === 'hour' ? 4 : 3; 444 var increment = event.keyCode === 37 ? -1 : event.keyCode === 38 ? -bigIncrement : event.keyCode == 39 ? 1 : bigIncrement; 445 increment *= mode === 'minute' ? 5 : 1; 446 var focusDate = module.get.focusDate() || module.get.date() || new Date(); 447 var year = focusDate.getFullYear() + (mode === 'year' ? increment : 0); 448 var month = focusDate.getMonth() + (mode === 'month' ? increment : 0); 449 var day = focusDate.getDate() + (mode === 'day' ? increment : 0); 450 var hour = focusDate.getHours() + (mode === 'hour' ? increment : 0); 451 var minute = focusDate.getMinutes() + (mode === 'minute' ? increment : 0); 452 var newFocusDate = new Date(year, month, day, hour, minute); 453 if (settings.type === 'time') { 454 newFocusDate = module.helper.mergeDateTime(focusDate, newFocusDate); 455 } 456 if (module.helper.isDateInRange(newFocusDate, mode)) { 457 module.set.focusDate(newFocusDate); 458 } 459 } else if (event.keyCode === 13) { 460 //enter 461 var mode = module.get.mode(); 462 var date = module.get.focusDate(); 463 if (date && !settings.isDisabled(date, mode)) { 464 module.selectDate(date); 465 } 466 //disable form submission: 467 event.preventDefault(); 468 event.stopPropagation(); 469 } 470 } 471 472 if (event.keyCode === 38 || event.keyCode === 40) { 473 //arrow-up || arrow-down 474 event.preventDefault(); //don't scroll 475 module.popup('show'); 476 } 477 }, 478 inputChange: function () { 479 var val = $input.val(); 480 var date = parser.date(val, settings); 481 module.set.date(date, false); 482 }, 483 inputFocus: function () { 484 $container.addClass(className.active); 485 }, 486 inputBlur: function () { 487 $container.removeClass(className.active); 488 if (settings.formatInput) { 489 var date = module.get.date(); 490 var text = formatter.datetime(date, settings); 491 $input.val(text); 492 } 493 }, 494 inputClick: function () { 495 module.popup('show'); 496 } 497 }, 498 499 get: { 500 date: function () { 501 return $module.data(metadata.date) || null; 502 }, 503 focusDate: function () { 504 return $module.data(metadata.focusDate) || null; 505 }, 506 startDate: function () { 507 var startModule = module.get.calendarModule(settings.startCalendar); 508 return (startModule ? startModule.get.date() : $module.data(metadata.startDate)) || null; 509 }, 510 endDate: function () { 511 var endModule = module.get.calendarModule(settings.endCalendar); 512 return (endModule ? endModule.get.date() : $module.data(metadata.endDate)) || null; 513 }, 514 monthOffset: function () { 515 return $module.data(metadata.monthOffset) || 0; 516 }, 517 mode: function () { 518 //only returns valid modes for the current settings 519 var mode = $module.data(metadata.mode) || settings.startMode; 520 var validModes = module.get.validModes(); 521 if ($.inArray(mode, validModes) >= 0) { 522 return mode; 523 } 524 return settings.type === 'time' ? 'hour' : 525 settings.type === 'month' ? 'month' : 526 settings.type === 'year' ? 'year' : 'day'; 527 }, 528 validModes: function () { 529 var validModes = []; 530 if (settings.type !== 'time') { 531 if (!settings.disableYear || settings.type === 'year') { 532 validModes.push('year'); 533 } 534 if (!(settings.disableMonth || settings.type === 'year') || settings.type === 'month') { 535 validModes.push('month'); 536 } 537 if (settings.type.indexOf('date') >= 0) { 538 validModes.push('day'); 539 } 540 } 541 if (settings.type.indexOf('time') >= 0) { 542 validModes.push('hour'); 543 if (!settings.disableMinute) { 544 validModes.push('minute'); 545 } 546 } 547 return validModes; 548 }, 549 isTouch: function () { 550 try { 551 document.createEvent('TouchEvent'); 552 return true; 553 } 554 catch (e) { 555 return false; 556 } 557 }, 558 calendarModule: function (selector) { 559 if (!selector) { 560 return null; 561 } 562 if (!(selector instanceof $)) { 563 selector = $module.parent().children(selector).first(); 564 } 565 //assume range related calendars are using the same namespace 566 return selector.data(moduleNamespace); 567 } 568 }, 569 570 set: { 571 date: function (date, updateInput, fireChange) { 572 updateInput = updateInput !== false; 573 fireChange = fireChange !== false; 574 date = module.helper.sanitiseDate(date); 575 date = module.helper.dateInRange(date); 576 577 var mode = module.get.mode(); 578 var text = formatter.datetime(date, settings); 579 if (fireChange && settings.onChange.call(element, date, text, mode) === false) { 580 return false; 581 } 582 583 module.set.focusDate(date); 584 585 if (settings.isDisabled(date, mode)) { 586 return false; 587 } 588 589 var endDate = module.get.endDate(); 590 if (!!endDate && !!date && date > endDate) { 591 //selected date is greater than end date in range, so clear end date 592 module.set.endDate(undefined); 593 } 594 module.set.dataKeyValue(metadata.date, date); 595 596 if (updateInput && $input.length) { 597 $input.val(text); 598 } 599 }, 600 startDate: function (date, refreshCalendar) { 601 date = module.helper.sanitiseDate(date); 602 var startModule = module.get.calendarModule(settings.startCalendar); 603 if (startModule) { 604 startModule.set.date(date); 605 } 606 module.set.dataKeyValue(metadata.startDate, date, refreshCalendar); 607 }, 608 endDate: function (date, refreshCalendar) { 609 date = module.helper.sanitiseDate(date); 610 var endModule = module.get.calendarModule(settings.endCalendar); 611 if (endModule) { 612 endModule.set.date(date); 613 } 614 module.set.dataKeyValue(metadata.endDate, date, refreshCalendar); 615 }, 616 focusDate: function (date, refreshCalendar, updateFocus, updateRange) { 617 date = module.helper.sanitiseDate(date); 618 date = module.helper.dateInRange(date); 619 var isDay = module.get.mode() === 'day'; 620 var oldFocusDate = module.get.focusDate(); 621 if (isDay && date && oldFocusDate) { 622 var yearDelta = date.getFullYear() - oldFocusDate.getFullYear(); 623 var monthDelta = yearDelta * 12 + date.getMonth() - oldFocusDate.getMonth(); 624 if (monthDelta) { 625 var monthOffset = module.get.monthOffset() - monthDelta; 626 module.set.monthOffset(monthOffset, false); 627 } 628 } 629 var changed = module.set.dataKeyValue(metadata.focusDate, date, refreshCalendar); 630 updateFocus = (updateFocus !== false && changed && refreshCalendar === false) || focusDateUsedForRange != updateRange; 631 focusDateUsedForRange = updateRange; 632 if (updateFocus) { 633 module.update.focus(updateRange); 634 } 635 }, 636 monthOffset: function (monthOffset, refreshCalendar) { 637 var multiMonth = Math.max(settings.multiMonth, 1); 638 monthOffset = Math.max(1 - multiMonth, Math.min(0, monthOffset)); 639 module.set.dataKeyValue(metadata.monthOffset, monthOffset, refreshCalendar); 640 }, 641 mode: function (mode, refreshCalendar) { 642 module.set.dataKeyValue(metadata.mode, mode, refreshCalendar); 643 }, 644 dataKeyValue: function (key, value, refreshCalendar) { 645 var oldValue = $module.data(key); 646 var equal = oldValue === value || (oldValue <= value && oldValue >= value); //equality test for dates and string objects 647 if (value) { 648 $module.data(key, value); 649 } else { 650 $module.removeData(key); 651 } 652 refreshCalendar = refreshCalendar !== false && !equal; 653 if (refreshCalendar) { 654 module.create.calendar(); 655 } 656 return !equal; 657 } 658 }, 659 660 selectDate: function (date, forceSet) { 661 var mode = module.get.mode(); 662 var complete = forceSet || mode === 'minute' || 663 (settings.disableMinute && mode === 'hour') || 664 (settings.type === 'date' && mode === 'day') || 665 (settings.type === 'month' && mode === 'month') || 666 (settings.type === 'year' && mode === 'year'); 667 if (complete) { 668 var canceled = module.set.date(date) === false; 669 if (!canceled && settings.closable) { 670 module.popup('hide'); 671 //if this is a range calendar, show the end date calendar popup and focus the input 672 var endModule = module.get.calendarModule(settings.endCalendar); 673 if (endModule) { 674 endModule.popup('show'); 675 endModule.focus(); 676 } 677 } 678 } else { 679 var newMode = mode === 'year' ? (!settings.disableMonth ? 'month' : 'day') : 680 mode === 'month' ? 'day' : mode === 'day' ? 'hour' : 'minute'; 681 module.set.mode(newMode); 682 if (mode === 'hour' || (mode === 'day' && module.get.date())) { 683 //the user has chosen enough to consider a valid date/time has been chosen 684 module.set.date(date); 685 } else { 686 module.set.focusDate(date); 687 } 688 } 689 }, 690 691 changeDate: function (date) { 692 module.set.date(date); 693 }, 694 695 clear: function () { 696 module.set.date(undefined); 697 }, 698 699 popup: function () { 700 return $activator.popup.apply($activator, arguments); 701 }, 702 703 focus: function () { 704 if ($input.length) { 705 $input.focus(); 706 } else { 707 $container.focus(); 708 } 709 }, 710 blur: function () { 711 if ($input.length) { 712 $input.blur(); 713 } else { 714 $container.blur(); 715 } 716 }, 717 718 helper: { 719 sanitiseDate: function (date) { 720 if (!date) { 721 return undefined; 722 } 723 if (!(date instanceof Date)) { 724 date = parser.date('' + date, settings); 725 } 726 if (isNaN(date.getTime())) { 727 return undefined; 728 } 729 return date; 730 }, 731 dateDiff: function (date1, date2, mode) { 732 mode = mode || 'day'; 733 var isTimeOnly = settings.type === 'time'; 734 var isYear = mode === 'year'; 735 var isYearOrMonth = isYear || mode === 'month'; 736 var isMinute = mode === 'minute'; 737 var isHourOrMinute = isMinute || mode === 'hour'; 738 //only care about a minute accuracy of 5 739 date1 = new Date( 740 isTimeOnly ? 2000 : date1.getFullYear(), 741 isTimeOnly ? 0 : isYear ? 0 : date1.getMonth(), 742 isTimeOnly ? 1 : isYearOrMonth ? 1 : date1.getDate(), 743 !isHourOrMinute ? 0 : date1.getHours(), 744 !isMinute ? 0 : 5 * Math.floor(date1.getMinutes() / 5)); 745 date2 = new Date( 746 isTimeOnly ? 2000 : date2.getFullYear(), 747 isTimeOnly ? 0 : isYear ? 0 : date2.getMonth(), 748 isTimeOnly ? 1 : isYearOrMonth ? 1 : date2.getDate(), 749 !isHourOrMinute ? 0 : date2.getHours(), 750 !isMinute ? 0 : 5 * Math.floor(date2.getMinutes() / 5)); 751 return date2.getTime() - date1.getTime(); 752 }, 753 dateEqual: function (date1, date2, mode) { 754 return !!date1 && !!date2 && module.helper.dateDiff(date1, date2, mode) === 0; 755 }, 756 isDateInRange: function (date, mode, minDate, maxDate) { 757 if (!minDate && !maxDate) { 758 var startDate = module.get.startDate(); 759 minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate; 760 maxDate = settings.maxDate; 761 } 762 minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), 5 * Math.ceil(minDate.getMinutes() / 5)); 763 return !(!date || 764 (minDate && module.helper.dateDiff(date, minDate, mode) > 0) || 765 (maxDate && module.helper.dateDiff(maxDate, date, mode) > 0)); 766 }, 767 dateInRange: function (date, minDate, maxDate) { 768 if (!minDate && !maxDate) { 769 var startDate = module.get.startDate(); 770 minDate = startDate && settings.minDate ? new Date(Math.max(startDate, settings.minDate)) : startDate || settings.minDate; 771 maxDate = settings.maxDate; 772 } 773 minDate = minDate && new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), minDate.getHours(), 5 * Math.ceil(minDate.getMinutes() / 5)); 774 var isTimeOnly = settings.type === 'time'; 775 return !date ? date : 776 (minDate && module.helper.dateDiff(date, minDate, 'minute') > 0) ? 777 (isTimeOnly ? module.helper.mergeDateTime(date, minDate) : minDate) : 778 (maxDate && module.helper.dateDiff(maxDate, date, 'minute') > 0) ? 779 (isTimeOnly ? module.helper.mergeDateTime(date, maxDate) : maxDate) : 780 date; 781 }, 782 mergeDateTime: function (date, time) { 783 return (!date || !time) ? time : 784 new Date(date.getFullYear(), date.getMonth(), date.getDate(), time.getHours(), time.getMinutes()); 785 } 786 }, 787 788 setting: function (name, value) { 789 module.debug('Changing setting', name, value); 790 if ($.isPlainObject(name)) { 791 $.extend(true, settings, name); 792 } 793 else if (value !== undefined) { 794 if ($.isPlainObject(settings[name])) { 795 $.extend(true, settings[name], value); 796 } 797 else { 798 settings[name] = value; 799 } 800 } 801 else { 802 return settings[name]; 803 } 804 }, 805 internal: function (name, value) { 806 module.debug('Changing internal', name, value); 807 if (value !== undefined) { 808 if ($.isPlainObject(name)) { 809 $.extend(true, module, name); 810 } 811 else { 812 module[name] = value; 813 } 814 } 815 else { 816 return module[name]; 817 } 818 }, 819 debug: function () { 820 if (!settings.silent && settings.debug) { 821 if (settings.performance) { 822 module.performance.log(arguments); 823 } 824 else { 825 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 826 module.debug.apply(console, arguments); 827 } 828 } 829 }, 830 verbose: function () { 831 if (!settings.silent && settings.verbose && settings.debug) { 832 if (settings.performance) { 833 module.performance.log(arguments); 834 } 835 else { 836 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 837 module.verbose.apply(console, arguments); 838 } 839 } 840 }, 841 error: function () { 842 if (!settings.silent) { 843 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 844 module.error.apply(console, arguments); 845 } 846 }, 847 performance: { 848 log: function (message) { 849 var 850 currentTime, 851 executionTime, 852 previousTime 853 ; 854 if (settings.performance) { 855 currentTime = new Date().getTime(); 856 previousTime = time || currentTime; 857 executionTime = currentTime - previousTime; 858 time = currentTime; 859 performance.push({ 860 'Name': message[0], 861 'Arguments': [].slice.call(message, 1) || '', 862 'Element': element, 863 'Execution Time': executionTime 864 }); 865 } 866 clearTimeout(module.performance.timer); 867 module.performance.timer = setTimeout(module.performance.display, 500); 868 }, 869 display: function () { 870 var 871 title = settings.name + ':', 872 totalTime = 0 873 ; 874 time = false; 875 clearTimeout(module.performance.timer); 876 $.each(performance, function (index, data) { 877 totalTime += data['Execution Time']; 878 }); 879 title += ' ' + totalTime + 'ms'; 880 if (moduleSelector) { 881 title += ' \'' + moduleSelector + '\''; 882 } 883 if ((console.group !== undefined || console.table !== undefined) && performance.length > 0) { 884 console.groupCollapsed(title); 885 if (console.table) { 886 console.table(performance); 887 } 888 else { 889 $.each(performance, function (index, data) { 890 console.log(data['Name'] + ': ' + data['Execution Time'] + 'ms'); 891 }); 892 } 893 console.groupEnd(); 894 } 895 performance = []; 896 } 897 }, 898 invoke: function (query, passedArguments, context) { 899 var 900 object = instance, 901 maxDepth, 902 found, 903 response 904 ; 905 passedArguments = passedArguments || queryArguments; 906 context = element || context; 907 if (typeof query == 'string' && object !== undefined) { 908 query = query.split(/[\. ]/); 909 maxDepth = query.length - 1; 910 $.each(query, function (depth, value) { 911 var camelCaseValue = (depth != maxDepth) 912 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 913 : query 914 ; 915 if ($.isPlainObject(object[camelCaseValue]) && (depth != maxDepth)) { 916 object = object[camelCaseValue]; 917 } 918 else if (object[camelCaseValue] !== undefined) { 919 found = object[camelCaseValue]; 920 return false; 921 } 922 else if ($.isPlainObject(object[value]) && (depth != maxDepth)) { 923 object = object[value]; 924 } 925 else if (object[value] !== undefined) { 926 found = object[value]; 927 return false; 928 } 929 else { 930 module.error(error.method, query); 931 return false; 932 } 933 }); 934 } 935 if ($.isFunction(found)) { 936 response = found.apply(context, passedArguments); 937 } 938 else if (found !== undefined) { 939 response = found; 940 } 941 if ($.isArray(returnedValue)) { 942 returnedValue.push(response); 943 } 944 else if (returnedValue !== undefined) { 945 returnedValue = [returnedValue, response]; 946 } 947 else if (response !== undefined) { 948 returnedValue = response; 949 } 950 return found; 951 } 952 }; 953 954 if (methodInvoked) { 955 if (instance === undefined) { 956 module.initialize(); 957 } 958 module.invoke(query); 959 } 960 else { 961 if (instance !== undefined) { 962 instance.invoke('destroy'); 963 } 964 module.initialize(); 965 } 966 }) 967 ; 968 return (returnedValue !== undefined) 969 ? returnedValue 970 : this 971 ; 972 }; 973 974 $.fn.calendar.settings = { 975 976 name: 'Calendar', 977 namespace: 'calendar', 978 979 silent: false, 980 debug: false, 981 verbose: false, 982 performance: false, 983 984 type: 'datetime', // picker type, can be 'datetime', 'date', 'time', 'month', or 'year' 985 firstDayOfWeek: 0, // day for first day column (0 = Sunday) 986 constantHeight: true, // add rows to shorter months to keep day calendar height consistent (6 rows) 987 today: false, // show a 'today/now' button at the bottom of the calendar 988 closable: true, // close the popup after selecting a date/time 989 monthFirst: true, // month before day when parsing/converting date from/to text 990 touchReadonly: true, // set input to readonly on touch devices 991 inline: false, // create the calendar inline instead of inside a popup 992 on: null, // when to show the popup (defaults to 'focus' for input, 'click' for others) 993 initialDate: null, // date to display initially when no date is selected (null = now) 994 startMode: false, // display mode to start in, can be 'year', 'month', 'day', 'hour', 'minute' (false = 'day') 995 minDate: null, // minimum date/time that can be selected, dates/times before are disabled 996 maxDate: null, // maximum date/time that can be selected, dates/times after are disabled 997 ampm: true, // show am/pm in time mode 998 disableYear: false, // disable year selection mode 999 disableMonth: false, // disable month selection mode 1000 disableMinute: false, // disable minute selection mode 1001 formatInput: true, // format the input text upon input blur and module creation 1002 startCalendar: null, // jquery object or selector for another calendar that represents the start date of a date range 1003 endCalendar: null, // jquery object or selector for another calendar that represents the end date of a date range 1004 multiMonth: 1, // show multiple months when in 'day' mode 1005 1006 // popup options ('popup', 'on', 'hoverable', and show/hide callbacks are overridden) 1007 popupOptions: { 1008 position: 'bottom left', 1009 lastResort: 'bottom left', 1010 prefer: 'opposite', 1011 hideOnScroll: false 1012 }, 1013 1014 text: { 1015 days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], 1016 months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], 1017 monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 1018 today: 'Today', 1019 now: 'Now', 1020 am: 'AM', 1021 pm: 'PM' 1022 }, 1023 1024 formatter: { 1025 header: function (date, mode, settings) { 1026 return mode === 'year' ? settings.formatter.yearHeader(date, settings) : 1027 mode === 'month' ? settings.formatter.monthHeader(date, settings) : 1028 mode === 'day' ? settings.formatter.dayHeader(date, settings) : 1029 mode === 'hour' ? settings.formatter.hourHeader(date, settings) : 1030 settings.formatter.minuteHeader(date, settings); 1031 }, 1032 yearHeader: function (date, settings) { 1033 var decadeYear = Math.ceil(date.getFullYear() / 10) * 10; 1034 return (decadeYear - 9) + ' - ' + (decadeYear + 2); 1035 }, 1036 monthHeader: function (date, settings) { 1037 return date.getFullYear(); 1038 }, 1039 dayHeader: function (date, settings) { 1040 var month = settings.text.months[date.getMonth()]; 1041 var year = date.getFullYear(); 1042 return month + ' ' + year; 1043 }, 1044 hourHeader: function (date, settings) { 1045 return settings.formatter.date(date, settings); 1046 }, 1047 minuteHeader: function (date, settings) { 1048 return settings.formatter.date(date, settings); 1049 }, 1050 dayColumnHeader: function (day, settings) { 1051 return settings.text.days[day]; 1052 }, 1053 datetime: function (date, settings) { 1054 if (!date) { 1055 return ''; 1056 } 1057 var day = settings.type === 'time' ? '' : settings.formatter.date(date, settings); 1058 var time = settings.type.indexOf('time') < 0 ? '' : settings.formatter.time(date, settings, false); 1059 var separator = settings.type === 'datetime' ? ' ' : ''; 1060 return day + separator + time; 1061 }, 1062 date: function (date, settings) { 1063 if (!date) { 1064 return ''; 1065 } 1066 var day = date.getDate(); 1067 var month = settings.text.months[date.getMonth()]; 1068 var year = date.getFullYear(); 1069 return settings.type === 'year' ? year : 1070 settings.type === 'month' ? month + ' ' + year : 1071 (settings.monthFirst ? month + ' ' + day : day + ' ' + month) + ', ' + year; 1072 }, 1073 time: function (date, settings, forCalendar) { 1074 if (!date) { 1075 return ''; 1076 } 1077 var hour = date.getHours(); 1078 var minute = date.getMinutes(); 1079 var ampm = ''; 1080 if (settings.ampm) { 1081 ampm = ' ' + (hour < 12 ? settings.text.am : settings.text.pm); 1082 hour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour; 1083 } 1084 return hour + ':' + (minute < 10 ? '0' : '') + minute + ampm; 1085 }, 1086 today: function (settings) { 1087 return settings.type === 'date' ? settings.text.today : settings.text.now; 1088 } 1089 }, 1090 1091 parser: { 1092 date: function (text, settings) { 1093 if (!text) { 1094 return null; 1095 } 1096 text = ('' + text).trim().toLowerCase(); 1097 if (text.length === 0) { 1098 return null; 1099 } 1100 1101 var i, j, k; 1102 var minute = -1, hour = -1, day = -1, month = -1, year = -1; 1103 var isAm = undefined; 1104 1105 var isTimeOnly = settings.type === 'time'; 1106 var isDateOnly = settings.type.indexOf('time') < 0; 1107 1108 var words = text.split(settings.regExp.dateWords); 1109 var numbers = text.split(settings.regExp.dateNumbers); 1110 1111 if (!isDateOnly) { 1112 //am/pm 1113 isAm = $.inArray(settings.text.am.toLowerCase(), words) >= 0 ? true : 1114 $.inArray(settings.text.pm.toLowerCase(), words) >= 0 ? false : undefined; 1115 1116 //time with ':' 1117 for (i = 0; i < numbers.length; i++) { 1118 var number = numbers[i]; 1119 if (number.indexOf(':') >= 0) { 1120 if (hour < 0 || minute < 0) { 1121 var parts = number.split(':'); 1122 for (k = 0; k < Math.min(2, parts.length); k++) { 1123 j = parseInt(parts[k]); 1124 if (isNaN(j)) { 1125 j = 0; 1126 } 1127 if (k === 0) { 1128 hour = j % 24; 1129 } else { 1130 minute = j % 60; 1131 } 1132 } 1133 } 1134 numbers.splice(i, 1); 1135 } 1136 } 1137 } 1138 1139 if (!isTimeOnly) { 1140 //textual month 1141 for (i = 0; i < words.length; i++) { 1142 var word = words[i]; 1143 if (word.length <= 0) { 1144 continue; 1145 } 1146 word = word.substring(0, Math.min(word.length, 3)); 1147 for (j = 0; j < settings.text.months.length; j++) { 1148 var monthString = settings.text.months[j]; 1149 monthString = monthString.substring(0, Math.min(word.length, Math.min(monthString.length, 3))).toLowerCase(); 1150 if (monthString === word) { 1151 month = j + 1; 1152 break; 1153 } 1154 } 1155 if (month >= 0) { 1156 break; 1157 } 1158 } 1159 1160 //year > 59 1161 for (i = 0; i < numbers.length; i++) { 1162 j = parseInt(numbers[i]); 1163 if (isNaN(j)) { 1164 continue; 1165 } 1166 if (j > 59) { 1167 year = j; 1168 numbers.splice(i, 1); 1169 break; 1170 } 1171 } 1172 1173 //numeric month 1174 if (month < 0) { 1175 for (i = 0; i < numbers.length; i++) { 1176 k = i > 1 || settings.monthFirst ? i : i === 1 ? 0 : 1; 1177 j = parseInt(numbers[k]); 1178 if (isNaN(j)) { 1179 continue; 1180 } 1181 if (1 <= j && j <= 12) { 1182 month = j; 1183 numbers.splice(k, 1); 1184 break; 1185 } 1186 } 1187 } 1188 1189 //day 1190 for (i = 0; i < numbers.length; i++) { 1191 j = parseInt(numbers[i]); 1192 if (isNaN(j)) { 1193 continue; 1194 } 1195 if (1 <= j && j <= 31) { 1196 day = j; 1197 numbers.splice(i, 1); 1198 break; 1199 } 1200 } 1201 1202 //year <= 59 1203 if (year < 0) { 1204 for (i = numbers.length - 1; i >= 0; i--) { 1205 j = parseInt(numbers[i]); 1206 if (isNaN(j)) { 1207 continue; 1208 } 1209 if (j < 99) { 1210 j += 2000; 1211 } 1212 year = j; 1213 numbers.splice(i, 1); 1214 break; 1215 } 1216 } 1217 } 1218 1219 if (!isDateOnly) { 1220 //hour 1221 if (hour < 0) { 1222 for (i = 0; i < numbers.length; i++) { 1223 j = parseInt(numbers[i]); 1224 if (isNaN(j)) { 1225 continue; 1226 } 1227 if (0 <= j && j <= 23) { 1228 hour = j; 1229 numbers.splice(i, 1); 1230 break; 1231 } 1232 } 1233 } 1234 1235 //minute 1236 if (minute < 0) { 1237 for (i = 0; i < numbers.length; i++) { 1238 j = parseInt(numbers[i]); 1239 if (isNaN(j)) { 1240 continue; 1241 } 1242 if (0 <= j && j <= 59) { 1243 minute = j; 1244 numbers.splice(i, 1); 1245 break; 1246 } 1247 } 1248 } 1249 } 1250 1251 if (minute < 0 && hour < 0 && day < 0 && month < 0 && year < 0) { 1252 return null; 1253 } 1254 1255 if (minute < 0) { 1256 minute = 0; 1257 } 1258 if (hour < 0) { 1259 hour = 0; 1260 } 1261 if (day < 0) { 1262 day = 1; 1263 } 1264 if (month < 0) { 1265 month = 1; 1266 } 1267 if (year < 0) { 1268 year = new Date().getFullYear(); 1269 } 1270 1271 if (isAm !== undefined) { 1272 if (isAm) { 1273 if (hour === 12) { 1274 hour = 0; 1275 } 1276 } else if (hour < 12) { 1277 hour += 12; 1278 } 1279 } 1280 1281 var date = new Date(year, month - 1, day, hour, minute); 1282 if (date.getMonth() !== month - 1 || date.getFullYear() !== year) { 1283 //month or year don't match up, switch to last day of the month 1284 date = new Date(year, month, 0, hour, minute); 1285 } 1286 return isNaN(date.getTime()) ? null : date; 1287 } 1288 }, 1289 1290 // callback when date changes, return false to cancel the change 1291 onChange: function (date, text, mode) { 1292 return true; 1293 }, 1294 1295 // callback before show animation, return false to prevent show 1296 onShow: function () { 1297 }, 1298 1299 // callback after show animation 1300 onVisible: function () { 1301 }, 1302 1303 // callback before hide animation, return false to prevent hide 1304 onHide: function () { 1305 }, 1306 1307 // callback after hide animation 1308 onHidden: function () { 1309 }, 1310 1311 // is the given date disabled? 1312 isDisabled: function (date, mode) { 1313 return false; 1314 }, 1315 1316 selector: { 1317 popup: '.ui.popup', 1318 input: 'input', 1319 activator: 'input' 1320 }, 1321 1322 regExp: { 1323 dateWords: /[^A-Za-z\u00C0-\u024F]+/g, 1324 dateNumbers: /[^\d:]+/g 1325 }, 1326 1327 error: { 1328 popup: 'UI Popup, a required component is not included in this page', 1329 method: 'The method you called is not defined.' 1330 }, 1331 1332 className: { 1333 calendar: 'calendar', 1334 active: 'active', 1335 popup: 'ui popup', 1336 grid: 'ui equal width grid', 1337 column: 'column', 1338 table: 'ui celled center aligned unstackable table', 1339 prev: 'prev link', 1340 next: 'next link', 1341 prevIcon: 'chevron left icon', 1342 nextIcon: 'chevron right icon', 1343 link: 'link', 1344 cell: 'link', 1345 disabledCell: 'disabled', 1346 adjacentCell: 'adjacent', 1347 activeCell: 'active', 1348 rangeCell: 'range', 1349 focusCell: 'focus', 1350 todayCell: 'today', 1351 today: 'today link' 1352 }, 1353 1354 metadata: { 1355 date: 'date', 1356 focusDate: 'focusDate', 1357 startDate: 'startDate', 1358 endDate: 'endDate', 1359 mode: 'mode', 1360 monthOffset: 'monthOffset' 1361 } 1362 }; 1363 1364})(jQuery, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.