Add indicator for events outside of field of view

I have a scheduler on my page using the calendar view, in “week” mode by default, 0-23 hours.
The height is limited so there are scroll bars in the calendar and events can be outside of view.
What I would like to do is to have an indicator in each day’s column if there is an event outside the view in the top or bottom with a small arrow. Much like it’s done in Outlook’s calendar for example.

From what I can see there is no native support for this feature?
Any suggestions how to add the arrow in the scheduler? I’ve managed to identify events outside of the view, but I haven’t managed to place the arrow correctly to indicate it.

The code I have, it uses JQuery and Font Awesome icons.

$('.dhx_cal_data').scroll(function () { $('.dhx_cal_event').each(function () { var id = $(this).attr('event_id'); if ($(this).offset().top + $(this).height() < $(this).parent().parent().offset().top) // Check if bottom edge of event is outside of top of visible area TODO: Some marigin for error, like mark even if 10px stick into visible area? { console.log('Event outside of top'); if ($('#mark_up_' + id).length > 0) $('#mark_up_' + id).show(); else $(this).parent().parent().append('<i id="mark_up_' + id + '" class="fa fa-arrow-up" style="top:' + $(this).parent().parent().offset().top + 'px; position:absolute; left: ' + $(this).parent().offset().left + 'px;"></i>'); // THIS SEEMS TO NOT BE PLACED CORRECTLY } else if ($(this).offset().top > $(this).parent().parent().offset().top + $(this).parent().parent().height() // Check if top of event is outside of bottom of visible area. ) { console.log('Event outside of bottom'); // TODO: Add arrow for events outside bottom } else { if ($('#mark_up_' + id).length > 0) $('#mark_up_' + id).hide(); if ($('#mark_down_' + id).length > 0) $('#mark_down_' + id).hide(); } }); } );

And I don’t think it’s necessary, but just to be clear this is how my scheduler is initialized:

scheduler.config.xml_date = "%Y-%m-%d %H:%i:%s";
        scheduler.config.first_hour = 0;
        scheduler.config.last_hour = 24;
        scheduler.config.scroll_hour = dayStart;
        scheduler.config.preserve_scroll = false;   
        scheduler.config.readonly = true;
        scheduler.attachEvent("onTemplatesReady", function () {
            scheduler.templates.event_text = function (start, end, event) {
                var iconHtml = "";
                if (checkBits(event.icons, 1)) // Exact time
                    iconHtml = iconHtml + '<i class="fa fa-clock-o dhtmlx_exacttime"></i>';
                if (checkBits(event.icons, 2))   // Quick task
                    iconHtml = iconHtml + '<div class="dhtmlx_quicktask" style="background-image: url(/images/icons/' + (event.textColor == '#FFFFFF' ? 'WB' : 'BW') + '/16/cal.png);"></div>';
                return iconHtml + event.text;
            }
        });
        scheduler.init('scheduler_besok', new Date(), "week");

Hello,
unfortunately there is no built-in support for the feature.
You can get the events that are outside the view port by checking viewport height, scroll position and height of the hour it a time scale

Please check this topic
viewtopic.php?f=6&t=37698&p=117162&hilit=scrollTop#p117162

Regarding the adding a button, you can place it with absolute positioning. I wouldn’t use method like following $(this).parent().parent() for navigating inside scheduler dom, since it’s really hard to tell which elements you are working with.
Note that the key elements of a scheduler always have a fixed class names which you can use, e.g.
docs.dhtmlx.com/scheduler/snippet/a4fff323

I see, it’s too bad it’s not implemented natively as I think it’s a fairly useful and commonly wanted feature

I didn’t really get much wiser from reading the linked topic, but I figured out my own solution by expanding on what I had. I still use the parent() operator to navigate the DOM, since I found t hat was an easy way to quickly find the right column the event is in, but I moved it into variables to increase readability.

Here is the finished code that others can use for some inspiration if they find this topic when attempting something similar:

$('.dhx_cal_data').scroll(function () {
            $('.dhx_cal_event').each(function () {
                var id = $(this).attr('event_id');
                var viewPort = $(this).parent().parent();
                var column = $(this).parent();
                var event = $(this);
                var arrowTopOffset = (viewPort.offset().top - column.offset().top + 7); // +7 to get a bit or air between arrow and top line, 5px to be used as overlap
                var arrowBottomOffset = (viewPort.height() + viewPort.offset().top - column.offset().top) - 15; // -15 since height of arrow is 8px, and 7px air

                if (event.offset().top + event.height() < viewPort.offset().top + 5)   // Check if bottom edge of event is outside of top of visible area. +5 for some overlap
                {
                    console.log('Event outside of top');
                    if ($('#mark_up_' + id).length > 0) {
                        $('#mark_up_' + id).show();
                        $('#mark_up_' + id).css('top', arrowTopOffset);
                    }
                    else
                        column.append('<i id="mark_up_' + id + '" class="fa fa-chevron-up" style="top:' + arrowTopOffset + 'px; position:absolute; left: 115px;"></i>');
                }
                else if (event.offset().top > viewPort.offset().top + viewPort.height() - 5) // Check if top of event is outside of bottom of visible area. -5 for some overlap
                {
                    console.log('Event outside of bottom');
                    if ($('#mark_down_' + id).length > 0) {
                        $('#mark_down_' + id).show();
                        $('#mark_down_' + id).css('top', arrowBottomOffset);
                    }
                    else
                        column.append('<i id="mark_down_' + id + '" class="fa fa-chevron-down" style="top:' + arrowBottomOffset + 'px; position:absolute; left: 115px;"></i>');
                }
                else
                {
                    if ($('#mark_up_' + id).length > 0)
                        $('#mark_up_' + id).hide();
                    if ($('#mark_down_' + id).length > 0)
                        $('#mark_down_' + id).hide();
                }
            });
          }
        );