PageSourceSearch

https://galleryclimatecoalition.org/scripts/artlogic_evocalender.j…=989b809&g=df5dbdf2f50b73e7c4e699672d5f0660

js galleryclimatecoalition.org collected 2026-09-24 10:52:12 UTC 49,246 bytes, 1,137 lines download raw bytes

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

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.