diff --git a/library/Icinga/Timeline/TimeLine.php b/library/Icinga/Timeline/TimeLine.php index 4af173a92..68d4c8047 100644 --- a/library/Icinga/Timeline/TimeLine.php +++ b/library/Icinga/Timeline/TimeLine.php @@ -340,6 +340,7 @@ class TimeLine extends Form '
'; } + $elements[] = ''; return implode('', $elements); } diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index 7429d89c8..7794d2ad1 100644 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -335,9 +335,9 @@ class ActionController extends Zend_Controller_Action /** * Detect whether the current request requires changes in the layout and apply them before rendering * - * @see Zend_Controller_Action::postDispatch() + * @see Zend_Controller_Action::preDispatch() */ - public function postDispatch() + public function preDispatch() { Benchmark::measure('Action::postDispatch()'); diff --git a/modules/monitoring/application/controllers/TimelineController.php b/modules/monitoring/application/controllers/TimelineController.php index 53a0a642d..4571bbb4f 100644 --- a/modules/monitoring/application/controllers/TimelineController.php +++ b/modules/monitoring/application/controllers/TimelineController.php @@ -48,6 +48,7 @@ class Monitoring_TimelineController extends ActionController $timeline->setConfiguration(Config::app()); $timeline->buildForm(); // Necessary in order to populate request parameters $timeline->populate($this->_request->getParams()); + $timeline->setAttrib('data-icinga-component', 'monitoring/timelineComponent'); list($displayRange, $forecastRange) = $this->buildTimeRanges($timeline->getInterval()); $timeline->setTimeRange($displayRange); $timeline->setDisplayData($this->loadData($displayRange)); diff --git a/modules/monitoring/public/js/timelineComponent.js b/modules/monitoring/public/js/timelineComponent.js new file mode 100644 index 000000000..368d8f861 --- /dev/null +++ b/modules/monitoring/public/js/timelineComponent.js @@ -0,0 +1,123 @@ +/*global Icinga:false, document: false, define:false require:false base_url:false console:false */ +// {{{ICINGA_LICENSE_HEADER}}} +/** + * This file is part of Icinga Web 2. + * + * Icinga Web 2 - Head for multiple monitoring backends. + * Copyright (C) 2013 Icinga Development Team + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @copyright 2013 Icinga Development Team + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + * + */ +// {{{ICINGA_LICENSE_HEADER}}} + +/** + * Provides infinite scrolling functionality for the monitoring timeline + */ +define(['jquery', 'logging'], function($, log) { + 'use strict'; + + return function() { + this.scrolled = false; + this.ignoreScroll = false; + + /** + * Scroll-event to register that the user has scrolled + */ + this.registerScroll = function() { + if (!this.ignoreScroll) { + this.scrolled = true; + } + }; + + /** + * Check whether the user has scrolled to the timeline's end + * and initiate the infinite scrolling if this is the case + */ + this.checkScroll = function() { + if (this.scrolled) { + if (this.isScrolledIntoView('#TimelineEnd')) { + this.ignoreScroll = true; + this.loadTimeline.bind(this)(); + } + this.scrolled = false; + } + + if ($('[name="Timeline"]').length > 0) { + setTimeout(this.checkScroll.bind(this), 1000); + } + }; + + /** + * Return whether the given element is visible in the users view + * + * Borrowed from: http://stackoverflow.com/q/487073 + * + * @param {selector} element The element to check + * @returns {Boolean} + */ + this.isScrolledIntoView = function(element) { + var docViewTop = $(window).scrollTop(); + var docViewBottom = docViewTop + $(window).height(); + + var elemTop = $(element).offset().top; + var elemBottom = elemTop + $(element).height(); + + return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom) + && (elemBottom <= docViewBottom) && (elemTop >= docViewTop)); + }; + + /** + * Return the current base url + * + * @returns {String} + */ + this.getBaseUrl = function() { + var protocol = window.location.protocol; + var host = window.location.host; + var base = window.base_url; + + return protocol + "//" + host + base; + } + + /** + * Initiate the AJAX timeline request + */ + this.loadTimeline = function() { + var query = {}; + var base_url = this.getBaseUrl(); + $.get(base_url + '/monitoring/timeline/extend', query, this.extendTimeline.bind(this)); + }; + + /** + * Process the AJAX timeline response + * + * @param {string} html + */ + this.extendTimeline = function(html) { + this.ignoreScroll = false; + // TODO: Implement the processing logic + } + + // The scroll-logic is split into two functions to avoid wasting too much + // performance by checking whether the user reached the end of the timeline + $(window).scroll(this.registerScroll.bind(this)); + setTimeout(this.checkScroll.bind(this), 1000); + }; +});