1/*! 2 * Evo Calendar - Simple and Modern-looking Event Calendar Plugin 3 * 4 * Licensed under the MIT License 5 * 6 * Version: 1.1.3 7 * Author: Edlyn Villegas 8 * Docs: https://edlynvillegas.github.com/evo-calendar 9 * Repo: https://github.com/edlynvillegas/evo-calendar 10 * Issues: https://github.com/edlynvillegas/evo-calendar/issues 11 * 12 */ 13 14;(function(factory) { 15 'use strict'; 16 if (typeof define === 'function' && define.amd) { 17 define(['jquery'], factory); 18 } else if (typeof exports !== 'undefined') { 19 module.exports = factory(require('jquery')); 20 } else { 21 factory(jQuery); 22 } 23 24}(function($) { 25 'use strict'; 26 var EvoCalendar = window.EvoCalendar || {}; 27 28 EvoCalendar = (function() { 29 var instanceUid = 0; 30 function EvoCalendar(element, settings) { 31 var _ = this; 32 _.defaults = { 33 theme: null, 34 format: 'mm/dd/yyyy', 35 titleFormat: 'MM yyyy', 36 eventHeaderFormat: 'MM d, yyyy', 37 firstDayOfWeek: 0, 38 language: 'en', 39 todayHighlight: false, 40 sidebarDisplayDefault: true, 41 sidebarToggler: true, 42 eventDisplayDefault: true, 43 eventListToggler: true, 44 calendarEvents: null 45 }; 46 _.options = $.extend({}, _.defaults, settings); 47 48 _.initials = { 49 default_class: $(element)[0].classList.value, 50 validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g, 51 dates: { 52 en: { 53 days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], 54 daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], 55 daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], 56 months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "
56November", "December"], 57 monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], 58 noEventForToday: "No event for today.. so take a rest! :)", 59 noEventForThisDay: "No event for this day.. so take a rest! :)", 60 previousYearText: "Previous year", 61 nextYearText: "Next year", 62 closeSidebarText: "Close sidebar", 63 closeEventListText: "Close event list" 64 }, 65 el: { 66 days: ["ÎÏ Ïιακή", "ÎÎµÏ ÏÎÏα", "ΤÏίÏη", "ΤεÏάÏÏη", "Î ÎμÏÏη", "ΠαÏαÏÎºÎµÏ Î®", "ΣάββαÏο"], 67 daysShort: ["ÎÏ Ï", "ÎÎµÏ ", "ΤÏί", "ΤεÏ", "Πεμ", "ΠαÏ", "Σάβ"], 68 daysMin: ["ÎÏ ", "Îε", "ΤÏ", "Τε", "Πε", "Πα", "Σά"], 69 months: ["ÎÎ±Î½Î¿Ï Î¬ÏιοÏ", "ΦεβÏÎ¿Ï Î¬ÏιοÏ", "ÎάÏÏιοÏ", "ÎÏÏίλιοÏ", "ÎάιοÏ", "ÎοÏνιοÏ", "ÎοÏλιοÏ", "ÎÏÎ³Î¿Ï ÏÏοÏ", "ΣεÏÏÎμβÏιοÏ", "ÎκÏÏβÏιοÏ", "ÎοÎμβÏιοÏ", "ÎεκÎμβÏιοÏ"], 70 monthsShort: ["Îαν", "Φεβ", "ÎαÏ", "ÎÏÏ", "Îάι", "ÎοÏν", "ÎοÏλ", "ÎÏγ", "ΣεÏ", "ÎκÏ", "ÎοÎ", "Îεκ"], 71 noEventForToday: "Îαμία εκδήλÏÏη για ÏήμεÏα.. Î¾ÎµÎºÎ¿Ï ÏαÏÏείÏε λοιÏÏν! :)", 72 noEventForThisDay: "Îαμία εκδήλÏÏη για Î±Ï Ïήν Ïην ημÎÏα.. οÏÏÏε Î¾ÎµÎºÎ¿Ï ÏαÏÏείÏε! :)", 73 previousYearText: "Î ÏοηγοÏμενο ÎÏοÏ", 74 nextYearText: "Î ÏοÏεÏÎÏ ÎÏοÏ", 75 closeSidebarText: "ÎλείÏιμο ÏλαÏÎ½Î®Ï Î³ÏαμμήÏ", 76 closeEventListText: "ÎλείÏιμο λίÏÏÎ±Ï ÏÏ Î¼Î²Î¬Î½ÏÏν" 77 }, 78 es: { 79 days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"], 80 daysShort: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb"], 81 daysMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa"], 82 months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"], 83 monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"], 84 noEventForToday: "No hay evento para hoy.. ¡asà que descanse! :)", 85 noEventForThisDay: "Ningún evento para este dÃa.. ¡asà que descanse! :)", 86 previousYearText: "Año anterior", 87 nextYearText: "El próximo año", 88 closeSidebarText: "Cerrar la barra lateral", 89 closeEventListText: "Cerrar la lista de eventos" 90 }, 91 de: { 92 days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], 93 daysShort: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], 94 daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], 95 months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], 96 monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"], 97 noEventForToday: "Keine Veranstaltung für heute.. also ruhen Sie sich aus! :)", 98 noEventForThisDay: "Keine Veranstaltung für diesen Tag.. also ruhen Sie sich aus! :)", 99 previousYearText: "Vorheriges Jahr", 100 nextYearText: "Nächstes Jahr", 101 closeSidebarText: "SchlieÃen Sie die Seitenleiste", 102 closeEventListText: "SchlieÃen Sie die Ereignisliste" 103 }, 104 pt: { 105 days: ["Domingo", "Segunda-Feira", "Terça-Feira", "Quarta-Feira", "Quinta-Feira", "Sexta-Feira", "SÃ
105¡bado"], 106 daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"], 107 daysMin: ["Do", "2a", "3a", "4a", "5a", "6a", "Sa"], 108 months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], 109 monthsShort: ["Jan", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"], 110 noEventForToday: "Nenhum evento para hoje.. então descanse! :)", 111 noEventForThisDay: "Nenhum evento para este dia.. então descanse! :)", 112 previousYearText: "Ano anterior", 113 nextYearText: "Próximo ano", 114 closeSidebarText: "Feche a barra lateral", 115 closeEventListText: "Feche a lista de eventos" 116 }, 117 fr: { 118 days: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"], 119 daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"], 120 daysMin: ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"], 121 months: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"], 122 monthsShort: ["Jan", "Fév", "Mar", "Avr", "Mai", "Juin", "Juil", "Août", "Sept", "Oct", "Nov", "Déc"], 123 noEventForToday: "Rien pour aujourd'hui... Belle journée :)", 124 noEventForThisDay: "Rien pour ce jour-ci... Profite de te réposer :)", 125 previousYearText: "Année précédente", 126 nextYearText: "L'année prochaine", 127 closeSidebarText: "Fermez la barre latérale", 128 closeEventListText: "Fermer la liste des événements" 129 }, 130 nl: { 131 days: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"], 132 daysShort: ["Zon", "Maan", "Din", "Woe", "Don", "Vrij", "Zat"], 133 daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za"], 134 months: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], 135 monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], 136 noEventForToday: "Geen event voor vandaag.. dus rust even uit! :)", 137 noEventForThisDay: "Geen event voor deze dag.. dus rust even uit! :)", 138 previousYearText: "Vorig jaar", 139 nextYearText: "Volgend jaar", 140 closeSidebarText: "Sluit de zijbalk", 141 closeEventListText: "Sluit de event lijst" 142 }, 143 id: { 144 days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"], 145 daysShort: ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"], 146 daysMin: ["Mi", "Sn", "Sl", "Ra", "Ka", "Ju", "Sa"], 147 months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"], 148 monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agu", "Sep", "Okt", "Nov", "Des"], 149 noEventForToday: "Tidak ada Acara untuk Sekarang.. Jadi Beristirahatlah! :)", 150 noEventForThisDay: "Tidak ada Acara untuk Hari Ini.. Jadi Beristirahatlah! :)", 151 previousYearText: "Tahun Sebelumnya", 152 nextYearText: "Tahun Berikutnya", 153 closeSidebarText: "Tutup Sidebar", 154 closeEventListText: "Tutup Daftar Acara" 155 } 156 } 157 } 158 _.initials.weekends = { 159 sun: _.initials.dates[_.options.language].daysShort[0], 160 sat: _.initials.dates[_.options.language].daysShort[6] 161 } 162 163 164 // Format Calendar Events into selected format 165 if(_.options.calendarEvents != null) { 166 for(var i=0; i < _.options.calendarEvents.length; i++) { 167 // If event doesn't have an id, throw an error message 168 if(!_.options.calendarEvents[i].id) { 169 console.log("%c Event named: \""+_.options.calendarEvents[i].name+"\" doesn't have a unique ID ", "color:white;font-weight:bold;background-color:#e21d1d;"); 170 } 171 if(_.isValidDate(_.options.calendarEvents[i].date)) {
172 _.options.calendarEvents[i].date = _.formatDate(_.options.calendarEvents[i].date, _.options.format) 173 } 174 } 175 } 176 177 // Global variables 178 _.startingDay = null; 179 _.monthLength = null; 180 _.windowW = $(window).width(); 181 182 // CURRENT 183 _.$current = { 184 month: (isNaN(this.month) || this.month == null) ? new Date().getMonth() : this.month, 185 year: (isNaN(this.year) || this.year == null) ? new Date().getFullYear() : this.year, 186 date: _.formatDate(_.initials.dates[_.defaults.language].months[new Date().getMonth()]+' '+new Date().getDate()+' '+ new Date().getFullYear(), _.options.format) 187 } 188 189 // ACTIVE 190 _.$active = { 191 month: _.$current.month, 192 year: _.$current.year, 193 date: _.$current.date, 194 event_date: _.$current.date, 195 events: [] 196 } 197 198 // LABELS 199 _.$label = { 200 days: [], 201 months: _.initials.dates[_.defaults.language].months, 202 days_in_month: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] 203 } 204 205 // HTML Markups (template) 206 _.$markups = { 207 calendarHTML: '', 208 mainHTML: '', 209 sidebarHTML: '', 210 eventHTML: '' 211 } 212 // HTML DOM elements 213 _.$elements = { 214 calendarEl: $(element), 215 innerEl: null, 216 sidebarEl: null, 217 eventEl: null, 218 219 sidebarToggler: null, 220 eventListToggler: null, 221 222 activeDayEl: null, 223 activeMonthEl: null, 224 activeYearEl: null 225 } 226 _.$breakpoints = { 227 tablet: 768, 228 mobile: 425 229 } 230 _.$UI = { 231 hasSidebar: true, 232 hasEvent: true 233 } 234 235 _.formatDate = $.proxy(_.formatDate, _); 236 _.selectDate = $.proxy(_.selectDate, _); 237 _.selectMonth = $.proxy(_.selectMonth, _); 238 _.selectYear = $.proxy(_.selectYear, _); 239 _.selectEvent = $.proxy(_.selectEvent, _); 240 _.toggleSidebar = $.proxy(_.toggleSidebar, _); 241 _.toggleEventList = $.proxy(_.toggleEventList, _); 242 243 _.instanceUid = instanceUid++; 244 245 _.init(true); 246 } 247 248 return EvoCalendar; 249 250 }()); 251 252 // v1.0.0 - Initialize plugin 253 EvoCalendar.prototype.init = function(init) { 254 var _ = this; 255 256 if (!$(_.$elements.calendarEl).hasClass('calendar-initialized')) { 257 $(_.$elements.calendarEl).addClass('evo-calendar calendar-initialized'); 258 if (_.windowW <= _.$breakpoints.tablet) { // tablet/mobile 259 _.toggleSidebar(false); 260 _.toggleEventList(false); 261 } else { 262 if (!_.options.sidebarDisplayDefault) _.toggleSidebar(false); 263 else _.toggleSidebar(true); 264 265 if (!_.options.eventDisplayDefault) _.toggleEventList(false); 266 else _.toggleEventList(true); 267 } 268 if (_.options.theme) _.setTheme(_.options.theme); // set calendar theme 269 _.buildTheBones(); // start building the calendar components 270 } 271 }; 272 // v1.0.0 - Destroy plugin 273 EvoCalendar.prototype.destroy = function() { 274 var _ = this; 275 // code here 276 _.destroyEventListener(); 277 if (_.$elements.calendarEl) { 278 _.$elements.calendarEl.removeClass('calendar-initialized'); 279 _.$elements.calendarEl.removeClass('evo-calendar'); 280 _.$elements.calendarEl.removeClass('sidebar-hide'); 281 _.$elements.calendarEl.removeClass('event-hide'); 282 } 283 _.$elements.calendarEl.empty(); 284 _.$elements.calendarEl.attr('class', _.initials.default_class); 285 $(_.$elements.calendarEl).trigger("destroy", [_]) 286 } 287 288 // v1.0.0 - Limit title (...) 289 EvoCalendar.prototype.limitTitle = function(title, limit) { 290 var newTitle = []; 291 limit = limit === undefined ? 18 : limit; 292 if ((title).split(' ').join('').length > limit) { 293 var t = title.split(' '); 294 for (var i=0; i<t.length; i++) { 295 if (t[i].length + newTitle.join('').length <= limit) { 296 newTitle.push(t[i]) 297 } 298 } 299 return newTitle.join(' ') + '...' 300 } 301 return title; 302 } 303 304 // v1.1.2 - Check and filter strings 305 EvoCalendar.prototype.stringCheck = function(d) { 306 return d.replace(/[^\w]/g, '\\$&'); 307 } 308 309 // v1.0.0 - Parse format (date) 310 EvoCalendar.prototype.parseFormat = function(format) { 311 var _ = this; 312 if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function') 313 return format; 314 // IE treats \0 as a string end in inputs (truncating the value), 315 // so it's a bad format delimiter, anyway 316 var separators = format.replace(_.initials.validParts, '\0').split('\0'), 317 parts = format.match(_.initials.validParts); 318 if (!separators || !separators.length || !parts || parts.length === 0){ 319 console.log("%c Invalid date format ", "color:white;font-weight:bold;background-color:#e21d1d;"); 320 } 321 return {separators: separators, parts: parts}; 322 }; 323 324 // v1.0.0 - Format date 325 EvoCalendar.prototype.formatDate = function(date, format, language) { 326 var _ = this; 327 if (!date) 328 return ''; 329 language = language ? language : _.defaults.language 330 if (typeof format === 'string') 331 format = _.parseFormat(format); 332 if (format.toDisplay) 333 return format.toDisplay(date, format, language); 334 335 var ndate = new Date(date); 336 // if (!_.isValidDate(ndate)) { // test 337 // ndate = new Date(date.replace(/-/g, '/')) 338 // } 339 340 var val = { 341 d: ndate.getDate(), 342 D: _.initials.dates[language].daysShort[ndate.getDay()], 343 DD: _.initials.dates[language].days[ndate.getDay()], 344 m: ndate.getMonth() + 1, 345 M: _.initials.dates[language].monthsShort[ndate.getMonth()], 346 MM: _.initials.dates[language].months[ndate.getMonth()], 347 yy: ndate.getFullYear().toString().substring(2), 348 yyyy: ndate.getFullYear() 349 }; 350 351 val.dd = (val.d < 10 ? '0' : '') + val.d; 352 val.mm = (val.m < 10 ? '0' : '') + val.m; 353 date = []; 354 var seps = $.extend([], format.separators); 355 for (var i=0, cnt = format.parts.length; i <= cnt; i++){ 356 if (seps.length) 357 date.push(seps.shift()); 358 date.push(val[format.parts[i]]); 359 } 360 return date.join(''); 361 }; 362 363 // v1.0.0 - Get dates between two dates 364 EvoCalendar.prototype.getBetweenDates = function(dates) { 365 var _ = this, betweenDates = []; 366 for (var x = 0; x < _.monthLength; x++) { 367 var active_date = _.formatDate(_.$label.months[_.$active.month] +' '+ (x + 1) +' '+ _.$active.year, _.options.format); 368 if (_.isBetweenDates(active_date, dates)) { 369 betweenDates.push(active_date); 370 } 371 } 372 return betweenDates; 373 }; 374 375 // v1.0.0 - Check if date is between the passed calendar date 376 EvoCalendar.prototype.isBetweenDates = function(active_date, dates) { 377 var sd, ed; 378 if (dates instanceof Array) { 379 sd = new Date(dates[0]); 380 ed = new Date(dates[1]); 381 } else { 382 sd = new Date(dates); 383 ed = new Date(dates); 384 } 385 if (sd <= new Date(active_date) && ed >= new Date(active_date)) { 386 return true; 387 } 388 return false;
389 } 390 391 // v1.0.0 - Check if event has the same event type in the same date 392 EvoCalendar.prototype.hasSameDayEventType = function(date, type) { 393 var _ = this, eventLength = 0; 394 395 for (var i = 0; i < _.options.calendarEvents.length; i++) { 396 if (_.options.calendarEvents[i].date instanceof Array) { 397 var arr = _.getBetweenDates(_.options.calendarEvents[i].date); 398 for (var x = 0; x < arr.length; x++) { 399 if(date === arr[x] && type === _.options.calendarEvents[i].type) { 400 eventLength++; 401 } 402 } 403 } else { 404 if(date === _.options.calendarEvents[i].date && type === _.options.calendarEvents[i].type) { 405 eventLength++; 406 } 407 } 408 } 409 410 if (eventLength > 0) { 411 return true; 412 } 413 return false; 414 } 415 416 // v1.0.0 - Set calendar theme 417 EvoCalendar.prototype.setTheme = function(themeName) { 418 var _ = this; 419 var prevTheme = _.options.theme; 420 _.options.theme = themeName.toLowerCase().split(' ').join('-'); 421 422 if (_.options.theme) $(_.$elements.calendarEl).removeClass(prevTheme); 423 if (_.options.theme !== 'default') $(_.$elements.calendarEl).addClass(_.options.theme); 424 } 425 426 // v1.0.0 - Called in every resize 427 EvoCalendar.prototype.resize = function() { 428 var _ = this; 429 _.windowW = $(window).width(); 430 431 if (_.windowW <= _.$breakpoints.tablet) { // tablet 432 _.toggleSidebar(false); 433 _.toggleEventList(false); 434 435 if (_.windowW <= _.$breakpoints.mobile) { // mobile 436 $(window) 437 .off('click.evocalendar.evo-' + _.instanceUid) 438 } else { 439 $(window) 440 .on('click.evocalendar.evo-' + _.instanceUid, $.proxy(_.toggleOutside, _)); 441 } 442 } else { 443 if (!_.options.sidebarDisplayDefault) _.toggleSidebar(false); 444 else _.toggleSidebar(true); 445 446 if (!_.options.eventDisplayDefault) _.toggleEventList(false); 447 else _.toggleEventList(true); 448 449 $(window) 450 .off('click.evocalendar.evo-' + _.instanceUid); 451 } 452 } 453 454 // v1.0.0 - Initialize event listeners 455 EvoCalendar.prototype.initEventListener = function() { 456 var _ = this; 457 458 // resize 459 $(window) 460 .off('resize.evocalendar.evo-' + _.instanceUid) 461 .on('resize.evocalendar.evo-' + _.instanceUid, $.proxy(_.resize, _)); 462 463 // IF sidebarToggler: set event listener: toggleSidebar 464 if(_.options.sidebarToggler) { 465 _.$elements.sidebarToggler 466 .off('click.evocalendar') 467 .on('click.evocalendar', _.toggleSidebar); 468 } 469 470 // IF eventListToggler: set event listener: toggleEventList 471 if(_.options.eventListToggler) { 472 _.$elements.eventListToggler 473 .off('click.evocalendar') 474 .on('click.evocalendar', _.toggleEventList); 475 } 476 477 // set event listener for each month 478 _.$elements.sidebarEl.find('[data-month-val]') 479 .off('click.evocalendar') 480 .on('click.evocalendar', _.selectMonth); 481 482 // set event listener for year 483 _.$elements.sidebarEl.find('[data-year-val]') 484 .off('click.evocalendar') 485 .on('click.evocalendar', _.selectYear); 486 487 // set event listener for every event listed 488 _.$elements.eventEl.find('[data-event-index]') 489 .off('click.evocalendar') 490 .on('click.evocalendar', _.selectEvent); 491 }; 492 493 // v1.0.0 - Destroy event listeners 494 EvoCalendar.prototype.destroyEventListener = function() { 495 var _ = this; 496 497 $(window).off('resize.evocalendar.evo-' + _.instanceUid); 498 $(window).off('click.evocalendar.evo-' + _.instanceUid); 499 500 // IF sidebarToggler: remove event listener: toggleSidebar 501 if(_.options.sidebarToggler) { 502 _.$elements.sidebarToggler 503 .off('click.evocalendar'); 504 } 505 506 // IF eventListToggler: remove event listener: toggleEventList 507 if(_.options.eventListToggler) { 508 _.$elements.eventListToggler 509 .off('click.evocalendar'); 510 } 511 512 // remove event listener for each day 513 _.$elements.innerEl.find('.calendar-day').children() 514 .off('click.evocalendar') 515 516 // remove event listener for each month 517 _.$elements.sidebarEl.find('[data-month-val]') 518 .off('click.evocalendar'); 519 520 // remove event listener for year 521 _.$elements.sidebarEl.find('[data-year-val]') 522 .off('click.evocalendar'); 523 524 // remove event listener for every event listed 525 _.$elements.eventEl.find('[data-event-index]') 526 .off('click.evocalendar'); 527 }; 528 529 // v1.0.0 - Calculate days (incl. monthLength, startingDays based on :firstDayOfWeekName) 530 EvoCalendar.prototype.calculateDays = function() { 531 var _ = this, nameDays, weekStart, firstDay; 532 _.monthLength = _.$label.days_in_month[_.$active.month];
532 // find number of days in month 533 if (_.$active.month == 1) { // compensate for leap year - february only! 534 if((_.$active.year % 4 == 0 && _.$active.year % 100 != 0) || _.$active.year % 400 == 0){ 535 _.monthLength = 29; 536 } 537 } 538 nameDays = _.initials.dates[_.options.language].daysShort; 539 weekStart = _.options.firstDayOfWeek; 540 541 while (_.$label.days.length < nameDays.length) { 542 if (weekStart == nameDays.length) { 543 weekStart=0; 544 } 545 _.$label.days.push(nameDays[weekStart]); 546 weekStart++; 547 } 548 firstDay = new Date(_.$active.year, _.$active.month).getDay() - weekStart; 549 _.startingDay = firstDay < 0 ? (_.$label.days.length + firstDay) : firstDay; 550 } 551 552 // v1.0.0 - Build the bones! (incl. sidebar, inner, events), called once in every initialization 553 EvoCalendar.prototype.buildTheBones = function() { 554 var _ = this; 555 _.calculateDays(); 556 557 if (!_.$elements.calendarEl.html()) { 558 var markup; 559 560 // --- BUILDING MARKUP BEGINS --- // 561 562 // sidebar 563 markup = '<div class="calendar-sidebar">'+ 564 '<div class="calendar-year">'+ 565 '<button class="icon-button" role="button" data-year-val="prev" title="'+_.initials.dates[_.options.language].previousYearText+'">'+ 566 '<span class="chevron-arrow-left"></span>'+ 567 '</button>'+ 568 ' <p></p> '+ 569 '<button class="icon-button" role="button" data-year-val="next" title="'+_.initials.dates[_.options.language].nextYearText+'">'+ 570 '<span class="chevron-arrow-right"></span>'+ 571 '</button>'+ 572 '</div><div class="month-list">'+ 573 '<ul class="calendar-months">'; 574 for(var i = 0; i < _.$label.months.length; i++) { 575 markup += '<li class="month" role="button" data-month-val="'+i+'">'+_.initials.dates[_.options.language].months[i]+'</li>'; 576 } 577 markup += '</ul>'; 578 markup += '</div></div>'; 579 580 // inner 581 markup += '<div class="calendar-inner">'+ 582 '<table class="calendar-table">'+ 583 '<tr><th colspan="7"></th></tr>'+ 584 '<tr class="calendar-header">'; 585 for(var i = 0; i < _.$label.days.length; i++ ){ 586 var headerClass = "calendar-header-day"; 587 if (_.$label.days[i] === _.initials.weekends.sat || _.$label.days[i] === _.initials.weekends.sun) { 588 headerClass += ' --weekend'; 589 } 590 markup += '<td class="'+headerClass+'">'+_.$label.days[i]+'</td>'; 591 } 592 markup += '</tr></table>'+ 593 '</div>'; 594 595 // events 596 markup += '<div class="calendar-events">'+ 597 '<div class="event-header"><p></p></div>'+ 598 '<div class="event-list"></div>'+ 599 '</div>'; 600 601 // --- Finally, build it now! --- // 602 _.$elements.calendarEl.html(markup); 603 604 if (!_.$elements.sidebarEl) _.$elements.sidebarEl = $(_.$elements.calendarEl).find('.calendar-sidebar'); 605 if (!_.$elements.innerEl) _.$elements.innerEl = $(_.$elements.calendarEl).find('.calendar-inner'); 606 if (!_.$elements.eventEl) _.$elements.eventEl = $(_.$elements.calendarEl).find('.calendar-events'); 607 608 // if: _.options.sidebarToggler 609 if(_.options.sidebarToggler) { 610 $(_.$elements.sidebarEl).append('<span id="sidebarToggler" role="button" aria-pressed title="'+_.initials.dates[_.options.language].closeSidebarText+'"><button class="icon-button"><span class="bars"></span></button></span>'); 611 if(!_.$elements.sidebarToggler) _.$elements.sidebarToggler = $(_.$elements.sidebarEl).find('span#sidebarToggler'); 612 } 613 if(_.options.eventListToggler) { 614 $(_.$elements.calendarEl).append('<span id="eventListToggler" role="button" aria-pressed title="'+_.initials.dates[_.options.language].closeEventListText+'"><button class="icon-button"><span class="chevron-arrow-right"></span></button></span>'); 615 if(!_.$elements.eventListToggler) _.$elements.eventListToggler = $(_.$elements.calendarEl).find('span#eventListToggler'); 616 } 617 } 618 619 _.buildSidebarYear(); 620 _.buildSidebarMonths();
621 _.buildCalendar(); 622 _.buildEventList(); 623 _.initEventListener(); // test 624 625 _.resize(); 626 } 627 628 // v1.0.0 - Build Event: Event list 629 EvoCalendar.prototype.buildEventList = function() { 630 var _ = this, markup, hasEventToday = false; 631 632 _.$active.events = []; 633 // Event date 634 var title = _.formatDate(_.$active.date, _.options.eventHeaderFormat, _.options.language); 635 _.$elements.eventEl.find('.event-header > p').text(title); 636 // Event list 637 var eventListEl = _.$elements.eventEl.find('.event-list'); 638 // Clear event list item(s) 639 if (eventListEl.children().length > 0) eventListEl.empty(); 640 if (_.options.calendarEvents) { 641 for (var i = 0; i < _.options.calendarEvents.length; i++) { 642 if(_.isBetweenDates(_.$active.date, _.options.calendarEvents[i].date)) { 643 eventAdder(_.options.calendarEvents[i]) 644 } 645 else if (_.options.calendarEvents[i].everyYear) { 646 var d = new Date(_.$active.date).getMonth() + 1 + ' ' + new Date(_.$active.date).getDate(); 647 var dd = new Date(_.options.calendarEvents[i].date).getMonth() + 1 + ' ' + new Date(_.options.calendarEvents[i].date).getDate(); 648 // var dates = [_.formatDate(_.options.calendarEvents[i].date[0], 'mm/dd'), _.formatDate(_.options.calendarEvents[i].date[1], 'mm/dd')]; 649 650 if(d==dd) { 651 eventAdder(_.options.calendarEvents[i]) 652 } 653 } 654 }; 655 } 656 function eventAdder(event) { 657 hasEventToday = true; 658 _.addEventList(event) 659 } 660 // IF: no event for the selected date 661 if(!hasEventToday) { 662 markup = '<div class="event-empty">'; 663 if (_.$active.date === _.$current.date) { 664 markup += '<p>'+_.initials.dates[_.options.language].noEventForToday+'</p>'; 665 } else { 666 markup += '<p>'+_.initials.dates[_.options.language].noEventForThisDay+'</p>'; 667 } 668 markup += '</div>'; 669 } 670 eventListEl.append(markup) 671 } 672 673 // v1.0.0 - Add single event to event list 674 EvoCalendar.prototype.addEventList = function(event_data) { 675 var _ = this, markup; 676 var eventListEl = _.$elements.eventEl.find('.event-list'); 677 if (eventListEl.find('[data-event-index]').length === 0) eventListEl.empty(); 678 _.$active.events.push(event_data); 679 markup = '<div class="event-container" role="button" data-event-index="'+(event_data.id)+'">'; 680 markup += '<div class="event-icon"><div class="event-bullet-'+event_data.type+'"'; 681 if (event_data.color) { 682 markup += 'style="background-color:'+event_data.color+'"' 683 } 684 markup += '></div></div><div class="event-info"><p class="event-title">'+_.limitTitle(event_data.name); 685 if (event_data.badge) markup += '<span>'+event_data.badge+'</span>'; 686 markup += '</p>' 687 if (event_data.description) markup += '<p class="event-desc">'+event_data.description+'</p>'; 688 markup += '</div>'; 689 markup += '</div>'; 690 eventListEl.append(markup); 691 692 _.$elements.eventEl.find('[data-event-index="'+(event_data.id)+'"]') 693 .off('click.evocalendar') 694 .on('click.evocalendar', _.selectEvent); 695 } 696 // v1.0.0 - Remove single event to event list 697 EvoCalendar.prototype.removeEventList = function(event_data) { 698 var _ = this, markup; 699 var eventListEl = _.$elements.eventEl.find('.event-list'); 700 if (eventListEl.find('[data-event-index="'+event_data+'"]').length === 0) return; // event not in active events 701 eventListEl.find('[data-event-index="'+event_data+'"]').remove(); 702 if (eventListEl.find('[data-event-index]').length === 0) { 703 eventListEl.empty(); 704 if (_.$active.date === _.$current.date) { 705 markup += '<p>'+_.initials.dates[_.options.language].noEventForToday+'</p>'; 706 } else { 707 markup += '<p>'+_.initials.dates[_.options.language].noEventForThisDay+'</p>'; 708 } 709 eventListEl.append(markup) 710 } 711 } 712 713 // v1.0.0 - Build Sidebar: Year text 714 EvoCalendar.prototype.buildSidebarYear = function() { 715 var _ = this; 716 717 _.$elements.sidebarEl.find('.calendar-year > p').text(_.$active.year); 718 } 719 720 // v1.0.0 - Build Sidebar: Months list text 721 EvoCalendar.prototype.buildSidebarMonths = function() { 722 var _ = this; 723 724 _.$elements.sidebarEl.find('.calendar-months > [data-month-val]').removeClass('active-month'); 725 _.$elements.sidebarEl.find('.calendar-months > [data-month-val="'+_.$active.month+'"]').addClass('active-month'); 726 } 727 728 // v1.0.0 - Build Calendar: Title, Days 729 EvoCalendar.prototype.buildCalendar = function() { 730 var _ = this, markup, title; 731 732 _.calculateDays(); 733 734 title = _.formatDate(new Date(_.$label.months[_.$active.month] +' 1 '+ _.$active.year), _.options.titleFormat, _.options.language); 735 _.$elements.innerEl.find('.calendar-table th').text(title); 736 737 _.$elements.innerEl.find('.calendar-body').remove(); // Clear days 738 739 markup += '<tr class="calendar-body">'; 740 var day = 1; 741 for (var i = 0; i < 9; i++) { // this loop is for is weeks (rows) 742 for (var j = 0; j < _.$label.days.length; j++) { // this loop is for weekdays (cells) 743 if (day <= _.monthLength && (i > 0 || j >= _.startingDay)) { 744 var dayClass = "calendar-day"; 745 if (_.$label.days[j] === _.initials.weekends.sat || _.$label.days[j] === _.initials.weekends.sun) { 746 dayClass += ' --weekend'; // add '--weekend' to sat sun 747 } 748 markup += '<td class="'+dayClass+'">'; 749 750 var thisDay = _.formatDate(_.$label.months[_.$active.month]+' '+day+' '+_.$active.year, _.options.format); 751 markup += '<div class="day" role="button" data-date-val="'+thisDay+'">'+day+'</div>'; 752 day++; 753 } else { 754 markup += '<td>'; 755 } 756 markup += '</td>'; 757 } 758 if (day > _.monthLength) { 759 break; // stop making rows if we've run out of days 760 } else { 761 markup += '</tr><tr class="calendar-body">'; // add if not 762 } 763 } 764 markup += '</tr>'; 765 _.$elements.innerEl.find('.calendar-table').append(markup); 766 767 if(_.options.todayHighlight) { 768 _.$elements.innerEl.find("[data-date-val='" + _.$current.date + "']").addClass('calendar-today'); 769 } 770 771 // set event listener for each day 772 _.$elements.innerEl.find('.calendar-day').children() 773 .off('click.evocalendar') 774 .on('click.evocalendar', _.selectDate) 775 776 var selectedDate = _.$elements.innerEl.find("[data-date-val='" + _.$active.date + "']"); 777 778 if (selectedDate) { 779 // Remove active class to all 780 _.$elements.innerEl.children().removeClass('calendar-active'); 781 // Add active class to selected date 782 selectedDate.addClass('calendar-active'); 783 } 784 if(_.options.calendarEvents != null) { // For event indicator (dots) 785 _.buildEventIndicator(); 786 } 787 }; 788 789 // v1.0.0 - Add event indicator/s (dots) 790 EvoCalendar.prototype.addEventIndicator = function(event) { 791 var _ = this, htmlToAppend, thisDate; 792 var event_date = event.date; 793 var type = _.stringCheck(event.type); 794 795 if (event_date instanceof Array) { 796 if (event.everyYear) { 797 for (var x=0; x<event_date.length; x++) { 798 event_date[x] = _.formatDate(new Date(event_date[x]).setFullYear(_.$active.year), _.options.format); 799 } 800 } 801 var active_date = _.getBetweenDates(event_date); 802 803 for (var i=0; i<active_date.length; i++) { 804 appendDot(active_date[i]); 805 } 806 } else { 807 if (event.everyYear) { 808 event_date = _.formatDate(new Date(event_date).setFullYear(_.$active.year), _.options.format); 809 } 810 appendDot(event_date); 811 } 812 813 function appendDot(date) { 814 thisDate = _.$elements.innerEl.find('[data-date-val="'+date+'"]'); 815 816 if (thisDate.find('span.event-indicator').length === 0) {
817 thisDate.append('<span class="event-indicator"></span>'); 818 } 819 820 if (thisDate.find('span.event-indicator > .type-bullet > .type-'+type).length === 0) { 821 htmlToAppend = '<div class="type-bullet"><div '; 822 823 htmlToAppend += 'class="type-'+event.type+'"' 824 if (event.color) { htmlToAppend += 'style="background-color:'+event.color+'"' } 825 htmlToAppend += '></div></div>'; 826 thisDate.find('.event-indicator').append(htmlToAppend); 827 } 828 } 829 }; 830 831 // v1.0.0 - Remove event indicator/s (dots) 832 EvoCalendar.prototype.removeEventIndicator = function(event) { 833 var _ = this; 834 var event_date = event.date; 835 var type = _.stringCheck(event.type); 836 837 if (event_date instanceof Array) { 838 var active_date = _.getBetweenDates(event_date); 839 840 for (var i=0; i<active_date.length; i++) { 841 removeDot(active_date[i]); 842 } 843 } else { 844 removeDot(event_date); 845 } 846 847 function removeDot(date) { 848 // Check if no '.event-indicator', 'cause nothing to remove 849 if (_.$elements.innerEl.find('[data-date-val="'+date+'"] span.event-indicator').length === 0) { 850 return; 851 } 852 853 // // If has no type of event, then delete 854 if (!_.hasSameDayEventType(date, type)) { 855 _.$elements.innerEl.find('[data-date-val="'+date+'"] span.event-indicator > .type-bullet > .type-'+type).parent().remove(); 856 } 857 } 858 }; 859 860 /**************** 861 * METHODS * 862 ****************/ 863 864 // v1.0.0 - Build event indicator on each date 865 EvoCalendar.prototype.buildEventIndicator = function() { 866 var _ = this; 867 868 // prevent duplication 869 _.$elements.innerEl.find('.calendar-day > day > .event-indicator').empty(); 870 871 for (var i = 0; i < _.options.calendarEvents.length; i++) { 872 _.addEventIndicator(_.options.calendarEvents[i]); 873 } 874 }; 875 876 // v1.0.0 - Select event 877 EvoCalendar.prototype.selectEvent = function(event) { 878 var _ = this; 879 var el = $(event.target).closest('.event-container'); 880 var id = $(el).data('eventIndex').toString(); 881 var index = _.options.calendarEvents.map(function (event) { return (event.id).toString() }).indexOf(id); 882 var modified_event = _.options.calendarEvents[index]; 883 if (modified_event.date instanceof Array) { 884 modified_event.dates_range = _.getBetweenDates(modified_event.date); 885 } 886 $(_.$elements.calendarEl).trigger("selectEvent", [_.options.calendarEvents[index]]) 887 } 888 889 // v1.0.0 - Select year 890 EvoCalendar.prototype.selectYear = function(event) { 891 var _ = this; 892 var el, yearVal; 893 894 if (typeof event === 'string' || typeof event === 'number') { 895 if ((parseInt(event)).toString().length === 4) { 896 yearVal = parseInt(event); 897 } 898 } else { 899 el = $(event.target).closest('[data-year-val]'); 900 yearVal = $(el).data('yearVal'); 901 } 902 903 if(yearVal == "prev") { 904 --_.$active.year; 905 } else if (yearVal == "next") { 906 ++_.$active.year; 907 } else if (typeof yearVal === 'number') { 908 _.$active.year = yearVal; 909 } 910 911 if (_.windowW <= _.$breakpoints.mobile) { 912 if(_.$UI.hasSidebar) _.toggleSidebar(false); 913 } 914 915 $(_.$elements.calendarEl).trigger("selectYear", [_.$active.year]) 916 917 _.buildSidebarYear(); 918 _.buildCalendar(); 919 }; 920 921 // v1.0.0 - Select month 922 EvoCalendar.prototype.selectMonth = function(event) { 923 var _ = this; 924 925 if (typeof event === 'string' || typeof event === 'number') { 926 if (event >= 0 && event <=_.$label.months.length) { 927 // if: 0-11 928 _.$active.month = (event).toString(); 929 } 930 } else { 931 // if month is manually selected 932 _.$active.month = $(event.currentTarget).data('monthVal'); 933 } 934 935 _.buildSidebarMonths();
936 _.buildCalendar(); 937 938 if (_.windowW <= _.$breakpoints.tablet) { 939 if(_.$UI.hasSidebar) _.toggleSidebar(false); 940 } 941 942 // EVENT FIRED: selectMonth 943 $(_.$elements.calendarEl).trigger("selectMonth", [_.initials.dates[_.options.language].months[_.$active.month], _.$active.month]) 944 }; 945 946 // v1.0.0 - Select specific date 947 EvoCalendar.prototype.selectDate = function(event) { 948 var _ = this; 949 var oldDate = _.$active.date; 950 var date, year, month, activeDayEl, isSameDate; 951 952 if (typeof event === 'string' || typeof event === 'number' || event instanceof Date) { 953 date = _.formatDate(new Date(event), _.options.format) 954 year = new Date(date).getFullYear(); 955 month = new Date(date).getMonth(); 956 957 if (_.$active.year !== year) _.selectYear(year); 958 if (_.$active.month !== month) _.selectMonth(month); 959 activeDayEl = _.$elements.innerEl.find("[data-date-val='" + date + "']"); 960 } else { 961 activeDayEl = $(event.currentTarget); 962 date = activeDayEl.data('dateVal') 963 } 964 isSameDate = _.$active.date === date; 965 // Set new active date 966 _.$active.date = date; 967 _.$active.event_date = date; 968 // Remove active class to all 969 _.$elements.innerEl.find('[data-date-val]').removeClass('calendar-active'); 970 // Add active class to selected date 971 activeDayEl.addClass('calendar-active'); 972 // Build event list if not the same date events built 973 if (!isSameDate) _.buildEventList(); 974 975 // EVENT FIRED: selectDate 976 $(_.$elements.calendarEl).trigger("selectDate", [_.$active.date, oldDate]) 977 }; 978 979 // v1.0.0 - Return active date 980 EvoCalendar.prototype.getActiveDate = function() { 981 var _ = this; 982 return _.$active.date; 983 } 984 985 // v1.0.0 - Return active events 986 EvoCalendar.prototype.getActiveEvents = function() { 987 var _ = this; 988 return _.$active.events; 989 } 990 991 // v1.0.0 - Hide Sidebar/Event List if clicked outside 992 EvoCalendar.prototype.toggleOutside = function(event) { 993 var _ = this, isInnerClicked; 994 995 isInnerClicked = event.target === _.$elements.innerEl[0]; 996 997 if (_.$UI.hasSidebar && isInnerClicked) _.toggleSidebar(false); 998 if (_.$UI.hasEvent && isInnerClicked) _.toggleEventList(false); 999 } 1000 1001 // v1.0.0 - Toggle Sidebar 1002 EvoCalendar.prototype.toggleSidebar = function(event) { 1003 var _ = this; 1004 1005 if (event === undefined || event.originalEvent) { 1006 $(_.$elements.calendarEl).toggleClass('sidebar-hide'); 1007 _.$UI.hasSidebar = !_.$UI.hasSidebar; 1008 } else { 1009 if(event) { 1010 $(_.$elements.calendarEl).removeClass('sidebar-hide'); 1011 _.$UI.hasSidebar = true; 1012 } else { 1013 $(_.$elements.calendarEl).addClass('sidebar-hide'); 1014 _.$UI.hasSidebar = false; 1015 } 1016 } 1017 1018 if (_.windowW <= _.$breakpoints.tablet) { 1019 if (_.$UI.hasSidebar && _.$UI.hasEvent) _.toggleEventList(); 1020 } 1021 }; 1022 1023 // v1.0.0 - Toggle Event list 1024 EvoCalendar.prototype.toggleEventList = function(event) { 1025 var _ = this; 1026 1027 if (event === undefined || event.originalEvent) { 1028 $(_.$elements.calendarEl).toggleClass('event-hide'); 1029 _.$UI.hasEvent = !_.$UI.hasEvent; 1030 } else { 1031 if(event) { 1032 $(_.$elements.calendarEl).removeClass('event-hide'); 1033 _.$UI.hasEvent = true; 1034 } else { 1035 $(_.$elements.calendarEl).addClass('event-hide'); 1036 _.$UI.hasEvent = false; 1037 } 1038 } 1039 1040 if (_.windowW <= _.$breakpoints.tablet) { 1041 if (_.$UI.hasEvent && _.$UI.hasSidebar) _.toggleSidebar(); 1042 } 1043 }; 1044 1045 // v1.0.0 - Add Calendar Event(s) 1046 EvoCalendar.prototype.addCalendarEvent = function(arr) { 1047 var _ = this; 1048 1049 function addEvent(data) { 1050 if(!data.id) {
1051 console.log("%c Event named: \""+data.name+"\" doesn't have a unique ID ", "color:white;font-weight:bold;background-color:#e21d1d;"); 1052 } 1053 1054 if (data.date instanceof Array) { 1055 for (var j=0; j < data.date.length; j++) { 1056 if(isDateValid(data.date[j])) { 1057 data.date[j] = _.formatDate(new Date(data.date[j]), _.options.format); 1058 } 1059 } 1060 } else { 1061 if(isDateValid(data.date)) { 1062 data.date = _.formatDate(new Date(data.date), _.options.format); 1063 } 1064 } 1065 1066 if (!_.options.calendarEvents) _.options.calendarEvents = []; 1067 _.options.calendarEvents.push(data); 1068 // add to date's indicator 1069 _.addEventIndicator(data); 1070 // add to event list IF active.event_date === data.date 1071 if (_.$active.event_date === data.date) _.addEventList(data); 1072 // _.$elements.innerEl.find("[data-date-val='" + data.date + "']") 1073 1074 function isDateValid(date) { 1075 if(_.isValidDate(date)) { 1076 return true; 1077 } else { 1078 console.log("%c Event named: \""+data.name+"\" has invalid date ", "color:white;font-weight:bold;background-color:#e21d1d;"); 1079 } 1080 return false; 1081 } 1082 } 1083 if (arr instanceof Array) { // Arrays of events 1084 for(var i=0; i < arr.length; i++) { 1085 addEvent(arr[i]) 1086 } 1087 } else if (typeof arr === 'object') { // Single event 1088 addEvent(arr) 1089 } 1090 }; 1091 1092 // v1.0.0 - Remove Calendar Event(s) 1093 EvoCalendar.prototype.removeCalendarEvent = function(arr) { 1094 var _ = this; 1095 1096 function deleteEvent(data) { 1097 // Array index 1098 var index = _.options.calendarEvents.map(function (event) { return event.id }).indexOf(data); 1099 1100 if (index >= 0) { 1101 var event = _.options.calendarEvents[index]; 1102 // Remove event from calendar events 1103 _.options.calendarEvents.splice(index, 1); 1104 // remove to event list 1105 _.removeEventList(data); 1106 // remove event indicator 1107 _.removeEventIndicator(event); 1108 } else { 1109 console.log("%c "+data+": ID not found ", "color:white;font-weight:bold;background-color:#e21d1d;"); 1110 } 1111 } 1112 if (arr instanceof Array) { // Arrays of index 1113 for(var i=0; i < arr.length; i++) { 1114 deleteEvent(arr[i]) 1115 } 1116 } else { // Single index 1117 deleteEvent(arr) 1118 } 1119 }; 1120 1121 // v1.0.0 - Check if date is valid 1122 EvoCalendar.prototype.isValidDate = function(d){ 1123 return new Date(d) && !isNaN(new Date(d).getTime()); 1124 } 1125 1126 $.fn.evoCalendar = function() { 1127 var _ = this, 1128 opt = arguments[0], 1129 args = Array.prototype.slice.call(arguments, 1), 1130 l = _.length, 1131 i, 1132 ret; 1133 for (i = 0; i < l; i++) { 1134 if (typeof opt == 'object' || typeof opt == 'undefined') 1135 _[i].evoCalendar = new EvoCalendar(_[i], opt); 1136 else 1137 ret = _[i].evoCalendar[opt].apply(_[i].evoCalendar, args); 1138 if (typeof ret != 'undefined') return ret; 1139 } 1140 return _; 1141 }; 1142 1143}));
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.