UNPKG

iobroker.vis

Version:

Graphical user interface for iobroker.

813 lines (705 loc) 30.7 kB
/* * jQuery SliderTabs v1.1 * http://lopatin.github.com/sliderTabs * * Copyright 2012, Alex Lopatin * Free to use under the MIT license. * http://www.opensource.org/licenses/mit-license.php * */ (function( $ ){ /* * The sliderTabs tabs class */ $.sliderTabs = function(container, options){ var plugin = this; var defaults = { autoplay: false, tabArrowWidth: 35, classes: { leftTabArrow: '', panel: '', panelActive: '', panelsContainer: '', rightTabArrow: '', tab: '', tabActive: '', tabsList: '' }, defaultTab: 1, height: null, indicators: false, mousewheel: true, position: "top", panelArrows: false, panelArrowsShowOnHover: false, tabs: true, tabHeight: 30, tabArrows: true, tabSlideLength: 100, tabSlideSpeed: 200, transition: 'slide', transitionEasing: 'easeOutCubic', transitionSpeed: 500, width: null }; // jQuery objects of important elements var $container = $(container), $indicators, $tabsList, $contentDivs, $tabsListContainer, $tabsListWrapper, $contentDivsContainer, $leftTabArrow, $rightTabArrow, $leftPanelArrow, $rightPanelArrow; // Locks to stop out of sync behavior var selectLock = false, heightLock = true; var settings, minMargin; // Index of currently selected tab plugin.selectedTab = defaults.defaultTab; plugin.init = function(){ settings = plugin.settings = $.extend({}, defaults, options); $container.addClass('ui-slider-tabs'); /* * Rebuild structure of container */ $contentDivs = $container.children("div").addClass('ui-slider-tab-content').remove(); // Tabs $tabsList = $container.children("ul").addClass('ui-slider-tabs-list').remove(); $tabsList.children("li").remove().appendTo($tabsList); plugin.count = $tabsList.children('li').length; $tabsListWrapper = $("<div class='ui-slider-tabs-list-wrapper'>"); $tabsListContainer = $("<div class='ui-slider-tabs-list-container'>").append($tabsList).appendTo($tabsListWrapper); $tabsListContainer.find('li').css('height', settings.tabHeight+2); $tabsListContainer.find('li a').css('height', settings.tabHeight+2); // Tab arrows $leftTabArrow = $("<a href='#' class='ui-slider-left-arrow'><div></div></a>").css({ 'width': settings.tabArrowWidth, 'height': settings.tabHeight+2 }).appendTo($tabsListContainer).click(function(e){ plugin.slideTabs('right', settings.tabSlideLength); return false; }); $rightTabArrow = $("<a href='#' class='ui-slider-right-arrow'><div></div></a>").css({ 'width': settings.tabArrowWidth, 'height': settings.tabHeight+2 }).appendTo($tabsListContainer).click(function(e){ plugin.slideTabs('left', settings.tabSlideLength); return false; }); // Content container $contentDivsContainer = $("<div class='ui-slider-tabs-content-container'>").append($contentDivs); // Position the tabs on top or bottom if(settings.position == 'bottom') $container.append($contentDivsContainer).append($tabsListWrapper.addClass('bottom')); else $container.append($tabsListWrapper).append($contentDivsContainer); if(settings.width) $container.width(parseInt(settings.width)); if(settings.height) $contentDivsContainer.height(parseInt(settings.height)- settings.tabHeight); // Create and show indicators if(settings.indicators) plugin.showIndicators(); // Select default tab plugin.selectTab(settings.defaultTab); plugin.slideTabs('left', 0); reorderPanels(); resizePanels(); // When tab is clicked $container.delegate('.ui-slider-tabs-list li a', 'click', function(){ if(!$(this).parent().hasClass('selected') && !selectLock){ plugin.selectTab($(this).parent()); } return false; }); // When indicator is clicked if($indicators) $indicators.delegate('.ui-slider-tabs-indicator', 'click', function(){ if(!$(this).hasClass('selected') && !selectLock) plugin.selectTab($(this).index()+1); }); // Set classes $.each(settings.classes, function(i, c){ switch(i){ case 'leftTabArrow': $leftTabArrow.addClass(c); break; case 'rightTabArrow': $rightTabArrow.addClass(c); break; case 'panel': $contentDivs.addClass(c); break; case 'panelsContainer': $contentDivsContainer.addClass(c); break; case 'tab': $tabsList.find('li').addClass(c); break; case 'tabsList': $tabsList.addClass(c); break; default: break; } }); // Panel arrows // Creates them if they don't exist if(settings.panelArrows) positionPanelArrows(); if(settings.panelArrowsShowOnHover){ if($leftPanelArrow) $leftPanelArrow.addClass('showOnHover'); if($rightPanelArrow) $rightPanelArrow.addClass('showOnHover'); } $contentDivsContainer.resize(positionPanelArrows); // Make responsive to changes in dimensions $tabsListWrapper.resize(function(){ resizeTabsList(); resizePanels(); }); // Resize content container height if inner panels change setInterval(function(){ var $panel = $contentDivsContainer.children('.selected'); if($panel.outerHeight() > $contentDivsContainer.outerHeight() && heightLock) resizeContentContainer($panel); }, 100); resizeTabsList(); // Hide tabs wrapper if option if false if(!settings.tabs) $tabsListWrapper.hide(); // Auto play if(settings.autoplay) setInterval(plugin.next, settings.autoplay); // Panel arrows // Mousehweel $container.bind('mousewheel', function(event, delta, deltaX, deltaY) { if(delta > 0) plugin.next(); else if(delta < 0) plugin.prev(); return false; }); } /* * Public methods */ // Select tab // param: tab is a tab index (1 ... n) or jQuery object of tab li element plugin.selectTab = function(tab){ heightLock = false; // Find $targetPanel, the panel to show var $clicked = (typeof tab === 'number') ? $tabsList.children("li:nth-child("+tab+")") : tab; var targetId = ($clicked.find('a').attr('href')).substr(1); var $targetPanel = $contentDivsContainer.children("#"+targetId); // Update selected tab plugin.selectedTab = (typeof tab === 'number') ? tab : tab.index()+1; // Resize the main contant container to the size of $targetPanel resizeContentContainer($targetPanel); // Lock selections until transitions finished selectLock = true; // Direction to slide panel on hide var direction = ($tabsList.find('.selected').index() < $clicked.index()) ? 'left' : 'right'; // Update selected classes $clicked.siblings().removeClass('selected'); if(settings.classes.tabActive != '') $clicked.siblings().removeClass(settings.classes.tabActive); $clicked.addClass('selected').addClass(settings.classes.tabActive); // Hide and show appropriate panels hidePanel($contentDivsContainer.children(".ui-slider-tab-content:visible"), direction); showPanel($targetPanel); // Slide tabs so that they fit in $tabsListContainer fitTabInContainer($clicked); // Select the proper indicator selectIndicator(); }; // Select the next (right) panel plugin.next = function(){ if(!selectLock){ if(plugin.count === plugin.selectedTab) plugin.selectTab(1); else plugin.selectTab(plugin.selectedTab+1); } }; // Select the previous panel plugin.prev = function(){ if(!selectLock){ if(plugin.selectedTab === 1) plugin.selectTab(plugin.count); else plugin.selectTab(plugin.selectedTab-1); } }; // Slide tabs left/right within $tabsListContainer plugin.slideTabs = function(direction, length){ var margin = parseInt($tabsList.css('margin-left')); var newMargin = margin; // Reset 'edge' classes on tab arrows $leftTabArrow.removeClass('edge'); $rightTabArrow.removeClass('edge'); // Calculate delta to slide by if(direction=='right') newMargin += length; else if(direction=='left') newMargin -= length; if(newMargin >= 0) { newMargin = 0; $leftTabArrow.addClass('edge'); } else if(newMargin <= minMargin){ newMargin = minMargin; $rightTabArrow.addClass('edge'); } // Animate $tabsList.animate({'margin-left': newMargin}, settings.tabSlideSpeed); }; // Show panel indicators // Create indicators if they don't exist yet plugin.showIndicators = function(){ if(!$indicators){ $indicators = $("<div class='ui-slider-tabs-indicator-container'>"); for(var i = 0; i < $contentDivs.length; i++){ $indicators.append("<div class='ui-slider-tabs-indicator'></div>"); } $contentDivsContainer.append($indicators); } else $indicators.show(); }; // Hide panel indicators plugin.hideIndicators = function(){ if($indicators) $indicators.hide(); }; // Show arrows that slide tabs left and right plugin.showTabArrows = function(){ if(!settings.tabArrows) return; $leftTabArrow.show(); $rightTabArrow.show(); $tabsListContainer.css('margin', '0 '+settings.tabArrowWidth+'px'); }; // Hide arrows that slide tabs left and right plugin.hideTabArrows = function(){ $leftTabArrow.hide(); $rightTabArrow.hide(); $tabsListContainer.css('margin', '0'); }; // Show panel arrows plugin.showPanelArrows = function(){ if($leftPanelArrow) $leftPanelArrow.show(); if($rightPanelArrow) $rightPanelArrow.show(); }; // Hide panel arrows plugin.hidePanelArrows = function(){ if($leftPanelArrow) $leftPanelArrow.hide(); if($rightPanelArrow) $rightPanelArrow.hide(); }; /* * Private methods */ // Add the selected class to the plugin.selectedTab tab. Remove from all others. var selectIndicator = function(){ if(settings.indicators && $indicators){ var $indicator = $indicators.children("div:nth-child("+plugin.selectedTab+")"); $indicator.siblings().removeClass('selected'); $indicator.addClass('selected'); } }; // Slide tabs inside of $tabsListContainer so that the selected one fits inside var fitTabInContainer = function(tab){ var tabOffset = tab.offset(), containerOffset = $tabsListContainer.offset(), leftOffset = tabOffset.left - containerOffset.left, rightOffset = (containerOffset.left + $tabsListContainer.outerWidth()) - (tabOffset.left + tab.outerWidth() ); if(leftOffset < 0) plugin.slideTabs('right', -leftOffset); else if(rightOffset < 0) plugin.slideTabs('left', -rightOffset); }; // Reposition content panels so that they are ready to be transitioned in and out. // This depends on whether the transition is set to slide or fade var reorderPanels = function(){ // Position content divs if(settings.transition == 'slide') // Move panels left/right basedon their index relative to the selected panel $tabsList.children('li').each(function(index, el){ var selectedIndex = $tabsList.children('.selected').index(), thisIndex = $(el).index(); var panel = $contentDivsContainer.children('#'+$(el).find('a').attr('href').substr(1)); if(selectedIndex < thisIndex) panel.css({left: $contentDivsContainer.width()+'px'}); else if(selectedIndex > thisIndex) panel.css({left: '-'+$contentDivsContainer.width()+'px'}); else panel.addClass(settings.classes.panelActive); }); if(settings.transition == 'fade') // Set opacity to correct value for non selected panels. $tabsList.children('li').each(function(index, el){ var selectedIndex = $tabsList.children('.selected').index(), thisIndex = $(el).index(); var panel = $contentDivsContainer.children('#'+$(el).find('a').attr('href').substr(1)); if(selectedIndex != thisIndex) panel.css({opacity: 0}); else panel.addClass(settings.classes.panelActive); }); }; // Object determining css properties to be animated to based on various actions, transitions, and directions var panelAnimationCSS = function(width){ return { hide: { slideleft: { left: '-'+width+'px' }, slideright: { left: width+'px' }, fade: { opacity: 0 } }, show: { slide: { left: 0 }, fade: { opacity: 1 } } } }; // Transition out the passed in panel. // param: panel is the jQuery object of the panel to be hidden // direction is either 'left' or 'right' for sliding transitions var hidePanel = function(panel, direction){ // Calculate correct key in panelAnimationCSS if(settings.transition == 'slide') var trans = 'slide'+direction; else var trans = settings.transition; // Animate the panel out panel.animate(panelAnimationCSS($contentDivsContainer.width())['hide'][trans], settings.transitionSpeed, settings.transitionEasing, function(){ panel.hide(); panel.removeClass('selected'); //if(settings.classes.panelActive != '') panel.removeClass(settings.classes.panelActive); selectLock = false; reorderPanels(); }); }; // Transition in the parameter panel // param: panel is the jQuery object of the panel to be shown var showPanel = function(panel){ // Show first panel.show(); panel.addClass(settings.classes.panelActive).addClass('selected'); // Then animate css properties panel.animate(panelAnimationCSS($contentDivsContainer.width())['show'][settings.transition], settings.transitionSpeed, settings.transitionEasing, function(){ selectLock = false; heightLock = true; reorderPanels(); }); }; // Animate the height of the content container to height target // params: target (int) is the new height var resizeContentContainer = function(target){ if(!settings.height) $contentDivsContainer.animate({ height: actualHeight(target) }, 200); }; // Position the panel arrows var positionPanelArrows = function(){ if(settings.panelArrows){ // Initialize them if you need to if(!$leftPanelArrow && !$rightPanelArrow){ $leftPanelArrow = $("<div class='ui-slider-tabs-leftPanelArrow'>").click(function(){ plugin.prev(); }); $rightPanelArrow = $("<div class='ui-slider-tabs-rightPanelArrow'>").click(function(){ plugin.next(); }); $leftPanelArrow.appendTo($contentDivsContainer); $rightPanelArrow.appendTo($contentDivsContainer); } // Set correct CSS 'top' attribute of each panel arrow $rightPanelArrow.css({ "top": $contentDivsContainer.height()/2 - $rightPanelArrow.outerHeight()/2 }); $leftPanelArrow.css({ "top": $contentDivsContainer.height()/2 - $leftPanelArrow.outerHeight()/2 }); } }; // Change the width of $tabsList to the sum of the outer widths of all tabs var resizeTabsList = function(){ // Calculate total width var width = 0; $tabsList.children().each(function(index, element){ width += $(element).outerWidth(true); }); // Set new width of $tabsList $tabsList.width(width); // Update minMargin. Hide tab arrows if no overflow if($tabsListContainer.width() < width && settings.tabArrows){ plugin.showTabArrows(); minMargin = $tabsListContainer.width() - width; } else plugin.hideTabArrows(); } // Resize indiviual panels to the width of the new container var resizePanels = function(){ $contentDivs.width($contentDivsContainer.width() - ($contentDivs.outerWidth() - $contentDivs.width())); }; // Get height of a hidden element var actualHeight = function(element){ var prevCSS = { 'display': element.css('display'), 'left': element.css('left'), 'position': element.css('position') }; element.css({ 'display': 'normal', 'left': -5000, 'position': 'absolute' }); var height = element.outerHeight(); element.css(prevCSS); return height; }; // Initialize the plugin plugin.init(); }; /* * Handle input. Call public functions and initializers */ $.fn.sliderTabs = function( data ) { return this.each(function(){ var _this = $(this), plugin = _this.data('sliderTabs'); // Method calling logic if (!plugin) { // If no plugin, initialize it plugin = new $.sliderTabs(this, data); _this.data('sliderTabs', plugin); return plugin; } if (plugin.methods[data]){ // If plugin exists, call a public method return plugin.methods[ data ].apply( this, Array.prototype.slice.call( arguments, 1 )); } }); }; })( jQuery ); /* * Additional easing functions * Taken from jQuery UI source code * * https://github.com/jquery/jquery-ui */ $.extend($.easing, { def: 'easeOutQuad', swing: function (x, t, b, c, d) { //alert($.easing.default); return $.easing[$.easing.def](x, t, b, c, d); }, easeInQuad: function (x, t, b, c, d) { return c*(t/=d)*t + b; }, easeOutQuad: function (x, t, b, c, d) { return -c *(t/=d)*(t-2) + b; }, easeInOutQuad: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t + b; return -c/2 * ((--t)*(t-2) - 1) + b; }, easeInCubic: function (x, t, b, c, d) { return c*(t/=d)*t*t + b; }, easeOutCubic: function (x, t, b, c, d) { return c*((t=t/d-1)*t*t + 1) + b; }, easeInOutCubic: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t + b; return c/2*((t-=2)*t*t + 2) + b; }, easeInQuart: function (x, t, b, c, d) { return c*(t/=d)*t*t*t + b; }, easeOutQuart: function (x, t, b, c, d) { return -c * ((t=t/d-1)*t*t*t - 1) + b; }, easeInOutQuart: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t*t + b; return -c/2 * ((t-=2)*t*t*t - 2) + b; }, easeInQuint: function (x, t, b, c, d) { return c*(t/=d)*t*t*t*t + b; }, easeOutQuint: function (x, t, b, c, d) { return c*((t=t/d-1)*t*t*t*t + 1) + b; }, easeInOutQuint: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; return c/2*((t-=2)*t*t*t*t + 2) + b; }, easeInSine: function (x, t, b, c, d) { return -c * Math.cos(t/d * (Math.PI/2)) + c + b; }, easeOutSine: function (x, t, b, c, d) { return c * Math.sin(t/d * (Math.PI/2)) + b; }, easeInOutSine: function (x, t, b, c, d) { return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; }, easeInExpo: function (x, t, b, c, d) { return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; }, easeOutExpo: function (x, t, b, c, d) { return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; }, easeInOutExpo: function (x, t, b, c, d) { if (t==0) return b; if (t==d) return b+c; if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; }, easeInCirc: function (x, t, b, c, d) { return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; }, easeOutCirc: function (x, t, b, c, d) { return c * Math.sqrt(1 - (t=t/d-1)*t) + b; }, easeInOutCirc: function (x, t, b, c, d) { if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; }, easeInElastic: function (x, t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; }, easeOutElastic: function (x, t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; }, easeInOutElastic: function (x, t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; }, easeInBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c*(t/=d)*t*((s+1)*t - s) + b; }, easeOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; }, easeInOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; }, easeInBounce: function (x, t, b, c, d) { return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b; }, easeOutBounce: function (x, t, b, c, d) { if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } }, easeInOutBounce: function (x, t, b, c, d) { if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; } }); /* * The following is the jQuery Mousewheel plugin. Full credit goes to * Brandon Aaron. (https://github.com/brandonaaron/jquery-mousewheel) * / /*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) * Licensed under the MIT License (LICENSE.txt). * * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. * Thanks to: Seamus Leahy for adding deltaX and deltaY * * Version: 3.0.6 * * Requires: 1.2.2+ */ (function($) { var types = ['DOMMouseScroll', 'mousewheel']; if ($.event.fixHooks) { for ( var i=types.length; i; ) { $.event.fixHooks[ types[--i] ] = $.event.mouseHooks; } } $.event.special.mousewheel = { setup: function() { if ( this.addEventListener ) { for ( var i=types.length; i; ) { this.addEventListener( types[--i], handler, false ); } } else { this.onmousewheel = handler; } }, teardown: function() { if ( this.removeEventListener ) { for ( var i=types.length; i; ) { this.removeEventListener( types[--i], handler, false ); } } else { this.onmousewheel = null; } } }; $.fn.extend({ mousewheel: function(fn) { return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); }, unmousewheel: function(fn) { return this.unbind("mousewheel", fn); } }); function handler(event) { var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0; event = $.event.fix(orgEvent); event.type = "mousewheel"; // Old school scrollwheel delta if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta/120; } if ( orgEvent.detail ) { delta = -orgEvent.detail/3; } // New school multidimensional scroll (touchpads) deltas deltaY = delta; // Gecko if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { deltaY = 0; deltaX = -1*delta; } // Webkit if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; } if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; } // Add event and delta to the front of the arguments args.unshift(event, delta, deltaX, deltaY); return ($.event.dispatch || $.event.handle).apply(this, args); } })(jQuery);