iobroker.vis
Version:
Graphical user interface for iobroker.
813 lines (705 loc) • 30.7 kB
JavaScript
/*
* 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);