forked from morrning/hesabixCore
2153 lines
53 KiB
JavaScript
2153 lines
53 KiB
JavaScript
/*!
|
|
* jQuery UI 1.8.22
|
|
*
|
|
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
* http://jquery.org/license
|
|
*
|
|
* http://docs.jquery.com/UI
|
|
*/
|
|
(function ($, undefined) {
|
|
// prevent duplicate loading
|
|
// this is only a problem because we proxy existing functions
|
|
// and we don't want to double proxy them
|
|
$.ui = $.ui || {};
|
|
if ($.ui.version) {
|
|
return;
|
|
}
|
|
|
|
$.extend($.ui, {
|
|
version: '1.8.22',
|
|
|
|
keyCode: {
|
|
ALT: 18,
|
|
BACKSPACE: 8,
|
|
CAPS_LOCK: 20,
|
|
COMMA: 188,
|
|
COMMAND: 91,
|
|
COMMAND_LEFT: 91, // COMMAND
|
|
COMMAND_RIGHT: 93,
|
|
CONTROL: 17,
|
|
DELETE: 46,
|
|
DOWN: 40,
|
|
END: 35,
|
|
ENTER: 13,
|
|
ESCAPE: 27,
|
|
HOME: 36,
|
|
INSERT: 45,
|
|
LEFT: 37,
|
|
MENU: 93, // COMMAND_RIGHT
|
|
NUMPAD_ADD: 107,
|
|
NUMPAD_DECIMAL: 110,
|
|
NUMPAD_DIVIDE: 111,
|
|
NUMPAD_ENTER: 108,
|
|
NUMPAD_MULTIPLY: 106,
|
|
NUMPAD_SUBTRACT: 109,
|
|
PAGE_DOWN: 34,
|
|
PAGE_UP: 33,
|
|
PERIOD: 190,
|
|
RIGHT: 39,
|
|
SHIFT: 16,
|
|
SPACE: 32,
|
|
TAB: 9,
|
|
UP: 38,
|
|
WINDOWS: 91, // COMMAND
|
|
},
|
|
});
|
|
|
|
// plugins
|
|
$.fn.extend({
|
|
propAttr: $.fn.prop || $.fn.attr,
|
|
|
|
_focus: $.fn.focus,
|
|
focus: function (delay, fn) {
|
|
return typeof delay === 'number'
|
|
? this.each(function () {
|
|
var elem = this;
|
|
setTimeout(function () {
|
|
$(elem).focus();
|
|
if (fn) {
|
|
fn.call(elem);
|
|
}
|
|
}, delay);
|
|
})
|
|
: this._focus.apply(this, arguments);
|
|
},
|
|
|
|
scrollParent: function () {
|
|
var scrollParent;
|
|
if (
|
|
($.browser.msie && /(static|relative)/.test(this.css('position'))) ||
|
|
/absolute/.test(this.css('position'))
|
|
) {
|
|
scrollParent = this.parents()
|
|
.filter(function () {
|
|
return (
|
|
/(relative|absolute|fixed)/.test($.curCSS(this, 'position', 1)) &&
|
|
/(auto|scroll)/.test(
|
|
$.curCSS(this, 'overflow', 1) +
|
|
$.curCSS(this, 'overflow-y', 1) +
|
|
$.curCSS(this, 'overflow-x', 1)
|
|
)
|
|
);
|
|
})
|
|
.eq(0);
|
|
} else {
|
|
scrollParent = this.parents()
|
|
.filter(function () {
|
|
return /(auto|scroll)/.test(
|
|
$.curCSS(this, 'overflow', 1) +
|
|
$.curCSS(this, 'overflow-y', 1) +
|
|
$.curCSS(this, 'overflow-x', 1)
|
|
);
|
|
})
|
|
.eq(0);
|
|
}
|
|
|
|
return /fixed/.test(this.css('position')) || !scrollParent.length
|
|
? $(document)
|
|
: scrollParent;
|
|
},
|
|
|
|
zIndex: function (zIndex) {
|
|
if (zIndex !== undefined) {
|
|
return this.css('zIndex', zIndex);
|
|
}
|
|
|
|
if (this.length) {
|
|
var elem = $(this[0]),
|
|
position,
|
|
value;
|
|
while (elem.length && elem[0] !== document) {
|
|
// Ignore z-index if position is set to a value where z-index is ignored by the browser
|
|
// This makes behavior of this function consistent across browsers
|
|
// WebKit always returns auto if the element is positioned
|
|
position = elem.css('position');
|
|
if (
|
|
position === 'absolute' ||
|
|
position === 'relative' ||
|
|
position === 'fixed'
|
|
) {
|
|
// IE returns 0 when zIndex is not specified
|
|
// other browsers return a string
|
|
// we ignore the case of nested elements with an explicit value of 0
|
|
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
|
|
value = parseInt(elem.css('zIndex'), 10);
|
|
if (!isNaN(value) && value !== 0) {
|
|
return value;
|
|
}
|
|
}
|
|
elem = elem.parent();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
},
|
|
|
|
disableSelection: function () {
|
|
return this.bind(
|
|
($.support.selectstart ? 'selectstart' : 'mousedown') +
|
|
'.ui-disableSelection',
|
|
function (event) {
|
|
event.preventDefault();
|
|
}
|
|
);
|
|
},
|
|
|
|
enableSelection: function () {
|
|
return this.off('.ui-disableSelection');
|
|
},
|
|
});
|
|
|
|
// support: jQuery <1.8
|
|
if (!$('<a>').outerWidth(1).jquery) {
|
|
$.each(['Width', 'Height'], function (i, name) {
|
|
var side = name === 'Width' ? ['Right', 'Left'] : ['Top', 'Bottom'],
|
|
type = name.toLowerCase(),
|
|
orig = {
|
|
innerWidth: $.fn.innerWidth,
|
|
innerHeight: $.fn.innerHeight,
|
|
outerWidth: $.fn.outerWidth,
|
|
outerHeight: $.fn.outerHeight,
|
|
};
|
|
|
|
function reduce(elem, size, border, margin) {
|
|
$.each(side, function () {
|
|
size -= parseFloat($.curCSS(elem, 'padding' + this, true)) || 0;
|
|
if (border) {
|
|
size -=
|
|
parseFloat($.curCSS(elem, 'border' + this + 'Width', true)) || 0;
|
|
}
|
|
if (margin) {
|
|
size -= parseFloat($.curCSS(elem, 'margin' + this, true)) || 0;
|
|
}
|
|
});
|
|
return size;
|
|
}
|
|
|
|
$.fn['inner' + name] = function (size) {
|
|
if (size === undefined) {
|
|
return orig['inner' + name].call(this);
|
|
}
|
|
|
|
return this.each(function () {
|
|
$(this).css(type, reduce(this, size) + 'px');
|
|
});
|
|
};
|
|
|
|
$.fn['outer' + name] = function (size, margin) {
|
|
if (typeof size !== 'number') {
|
|
return orig['outer' + name].call(this, size);
|
|
}
|
|
|
|
return this.each(function () {
|
|
$(this).css(type, reduce(this, size, true, margin) + 'px');
|
|
});
|
|
};
|
|
});
|
|
}
|
|
|
|
// selectors
|
|
function focusable(element, isTabIndexNotNaN) {
|
|
var nodeName = element.nodeName.toLowerCase();
|
|
if ('area' === nodeName) {
|
|
var map = element.parentNode,
|
|
mapName = map.name,
|
|
img;
|
|
if (!element.href || !mapName || map.nodeName.toLowerCase() !== 'map') {
|
|
return false;
|
|
}
|
|
img = $('img[usemap=#' + mapName + ']')[0];
|
|
return !!img && visible(img);
|
|
}
|
|
return (
|
|
(/input|select|textarea|button|object/.test(nodeName)
|
|
? !element.disabled
|
|
: 'a' == nodeName
|
|
? element.href || isTabIndexNotNaN
|
|
: isTabIndexNotNaN) &&
|
|
// the element and all of its ancestors must be visible
|
|
visible(element)
|
|
);
|
|
}
|
|
|
|
function visible(element) {
|
|
return !$(element)
|
|
.parents()
|
|
.andSelf()
|
|
.filter(function () {
|
|
return (
|
|
$.curCSS(this, 'visibility') === 'hidden' ||
|
|
$.expr.filters.hidden(this)
|
|
);
|
|
}).length;
|
|
}
|
|
|
|
$.extend($.expr[':'], {
|
|
data: $.expr.createPseudo
|
|
? $.expr.createPseudo(function (dataName) {
|
|
return function (elem) {
|
|
return !!$.data(elem, dataName);
|
|
};
|
|
})
|
|
: // support: jQuery <1.8
|
|
function (elem, i, match) {
|
|
return !!$.data(elem, match[3]);
|
|
},
|
|
|
|
focusable: function (element) {
|
|
return focusable(element, !isNaN($.attr(element, 'tabindex')));
|
|
},
|
|
|
|
tabbable: function (element) {
|
|
var tabIndex = $.attr(element, 'tabindex'),
|
|
isTabIndexNaN = isNaN(tabIndex);
|
|
return (
|
|
(isTabIndexNaN || tabIndex >= 0) && focusable(element, !isTabIndexNaN)
|
|
);
|
|
},
|
|
});
|
|
|
|
// support
|
|
$(function () {
|
|
var body = document.body,
|
|
div = body.appendChild((div = document.createElement('div')));
|
|
|
|
// access offsetHeight before setting the style to prevent a layout bug
|
|
// in IE 9 which causes the elemnt to continue to take up space even
|
|
// after it is removed from the DOM (#8026)
|
|
div.offsetHeight;
|
|
|
|
$.extend(div.style, {
|
|
minHeight: '100px',
|
|
height: 'auto',
|
|
padding: 0,
|
|
borderWidth: 0,
|
|
});
|
|
|
|
$.support.minHeight = div.offsetHeight === 100;
|
|
$.support.selectstart = 'onselectstart' in div;
|
|
|
|
// set display to none to avoid a layout bug in IE
|
|
// http://dev.jquery.com/ticket/4014
|
|
body.removeChild(div).style.display = 'none';
|
|
});
|
|
|
|
// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
|
|
if (!$.curCSS) {
|
|
$.curCSS = $.css;
|
|
}
|
|
|
|
// deprecated
|
|
$.extend($.ui, {
|
|
// $.ui.plugin is deprecated. Use the proxy pattern instead.
|
|
plugin: {
|
|
add: function (module, option, set) {
|
|
var proto = $.ui[module].prototype;
|
|
for (var i in set) {
|
|
proto.plugins[i] = proto.plugins[i] || [];
|
|
proto.plugins[i].push([option, set[i]]);
|
|
}
|
|
},
|
|
call: function (instance, name, args) {
|
|
var set = instance.plugins[name];
|
|
if (!set || !instance.element[0].parentNode) {
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i < set.length; i++) {
|
|
if (instance.options[set[i][0]]) {
|
|
set[i][1].apply(instance.element, args);
|
|
}
|
|
}
|
|
},
|
|
},
|
|
|
|
// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
|
|
contains: function (a, b) {
|
|
return document.compareDocumentPosition
|
|
? a.compareDocumentPosition(b) & 16
|
|
: a !== b && a.contains(b);
|
|
},
|
|
|
|
// only used by resizable
|
|
hasScroll: function (el, a) {
|
|
//If overflow is hidden, the element might have extra content, but the user wants to hide it
|
|
if ($(el).css('overflow') === 'hidden') {
|
|
return false;
|
|
}
|
|
|
|
var scroll = a && a === 'right' ? 'scrollLeft' : 'scrollTop',
|
|
has = false;
|
|
|
|
if (el[scroll] > 0) {
|
|
return true;
|
|
}
|
|
|
|
// TODO: determine which cases actually cause this to happen
|
|
// if the element doesn't have the scroll set, see if it's possible to
|
|
// set the scroll
|
|
el[scroll] = 1;
|
|
has = el[scroll] > 0;
|
|
el[scroll] = 0;
|
|
return has;
|
|
},
|
|
|
|
// these are odd functions, fix the API or move into individual plugins
|
|
isOverAxis: function (x, reference, size) {
|
|
//Determines when x coordinate is over "b" element axis
|
|
return x > reference && x < reference + size;
|
|
},
|
|
isOver: function (y, x, top, right, height, width) {
|
|
//Determines when x, y coordinates is over "b" element
|
|
return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, right, width);
|
|
},
|
|
});
|
|
})(jQuery);
|
|
/*!
|
|
* jQuery UI Widget 1.8.22
|
|
*
|
|
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
* http://jquery.org/license
|
|
*
|
|
* http://docs.jquery.com/UI/Widget
|
|
*/
|
|
(function ($, undefined) {
|
|
// jQuery 1.4+
|
|
if ($.cleanData) {
|
|
var _cleanData = $.cleanData;
|
|
$.cleanData = function (elems) {
|
|
for (var i = 0, elem; (elem = elems[i]) != null; i++) {
|
|
try {
|
|
$(elem).triggerHandler('remove');
|
|
// http://bugs.jquery.com/ticket/8235
|
|
} catch (e) {}
|
|
}
|
|
_cleanData(elems);
|
|
};
|
|
} else {
|
|
var _remove = $.fn.remove;
|
|
$.fn.remove = function (selector, keepData) {
|
|
return this.each(function () {
|
|
if (!keepData) {
|
|
if (!selector || $.filter(selector, [this]).length) {
|
|
$('*', this)
|
|
.add([this])
|
|
.each(function () {
|
|
try {
|
|
$(this).triggerHandler('remove');
|
|
// http://bugs.jquery.com/ticket/8235
|
|
} catch (e) {}
|
|
});
|
|
}
|
|
}
|
|
return _remove.call($(this), selector, keepData);
|
|
});
|
|
};
|
|
}
|
|
|
|
$.widget = function (name, base, prototype) {
|
|
var namespace = name.split('.')[0],
|
|
fullName;
|
|
name = name.split('.')[1];
|
|
fullName = namespace + '-' + name;
|
|
|
|
if (!prototype) {
|
|
prototype = base;
|
|
base = $.Widget;
|
|
}
|
|
|
|
// create selector for plugin
|
|
$.expr[':'][fullName] = function (elem) {
|
|
return !!$.data(elem, name);
|
|
};
|
|
|
|
$[namespace] = $[namespace] || {};
|
|
$[namespace][name] = function (options, element) {
|
|
// allow instantiation without initializing for simple inheritance
|
|
if (arguments.length) {
|
|
this._createWidget(options, element);
|
|
}
|
|
};
|
|
|
|
var basePrototype = new base();
|
|
// we need to make the options hash a property directly on the new instance
|
|
// otherwise we'll modify the options hash on the prototype that we're
|
|
// inheriting from
|
|
// $.each( basePrototype, function( key, val ) {
|
|
// if ( $.isPlainObject(val) ) {
|
|
// basePrototype[ key ] = $.extend( {}, val );
|
|
// }
|
|
// });
|
|
basePrototype.options = $.extend(true, {}, basePrototype.options);
|
|
$[namespace][name].prototype = $.extend(
|
|
true,
|
|
basePrototype,
|
|
{
|
|
namespace: namespace,
|
|
widgetName: name,
|
|
widgetEventPrefix:
|
|
$[namespace][name].prototype.widgetEventPrefix || name,
|
|
widgetBaseClass: fullName,
|
|
},
|
|
prototype
|
|
);
|
|
|
|
$.widget.bridge(name, $[namespace][name]);
|
|
};
|
|
|
|
$.widget.bridge = function (name, object) {
|
|
$.fn[name] = function (options) {
|
|
var isMethodCall = typeof options === 'string',
|
|
args = Array.prototype.slice.call(arguments, 1),
|
|
returnValue = this;
|
|
|
|
// allow multiple hashes to be passed on init
|
|
options =
|
|
!isMethodCall && args.length
|
|
? $.extend.apply(null, [true, options].concat(args))
|
|
: options;
|
|
|
|
// prevent calls to internal methods
|
|
if (isMethodCall && options.charAt(0) === '_') {
|
|
return returnValue;
|
|
}
|
|
|
|
if (isMethodCall) {
|
|
this.each(function () {
|
|
var instance = $.data(this, name),
|
|
methodValue =
|
|
instance && $.isFunction(instance[options])
|
|
? instance[options].apply(instance, args)
|
|
: instance;
|
|
// TODO: add this back in 1.9 and use $.error() (see #5972)
|
|
// if ( !instance ) {
|
|
// throw "cannot call methods on " + name + " prior to initialization; " +
|
|
// "attempted to call method '" + options + "'";
|
|
// }
|
|
// if ( !$.isFunction( instance[options] ) ) {
|
|
// throw "no such method '" + options + "' for " + name + " widget instance";
|
|
// }
|
|
// var methodValue = instance[ options ].apply( instance, args );
|
|
if (methodValue !== instance && methodValue !== undefined) {
|
|
returnValue = methodValue;
|
|
return false;
|
|
}
|
|
});
|
|
} else {
|
|
this.each(function () {
|
|
var instance = $.data(this, name);
|
|
if (instance) {
|
|
instance.option(options || {})._init();
|
|
} else {
|
|
$.data(this, name, new object(options, this));
|
|
}
|
|
});
|
|
}
|
|
|
|
return returnValue;
|
|
};
|
|
};
|
|
|
|
$.Widget = function (options, element) {
|
|
// allow instantiation without initializing for simple inheritance
|
|
if (arguments.length) {
|
|
this._createWidget(options, element);
|
|
}
|
|
};
|
|
|
|
$.Widget.prototype = {
|
|
widgetName: 'widget',
|
|
widgetEventPrefix: '',
|
|
options: {
|
|
disabled: false,
|
|
},
|
|
_createWidget: function (options, element) {
|
|
// $.widget.bridge stores the plugin instance, but we do it anyway
|
|
// so that it's stored even before the _create function runs
|
|
$.data(element, this.widgetName, this);
|
|
this.element = $(element);
|
|
this.options = $.extend(
|
|
true,
|
|
{},
|
|
this.options,
|
|
this._getCreateOptions(),
|
|
options
|
|
);
|
|
|
|
var self = this;
|
|
this.element.bind('remove.' + this.widgetName, function () {
|
|
self.destroy();
|
|
});
|
|
|
|
this._create();
|
|
this._trigger('create');
|
|
this._init();
|
|
},
|
|
_getCreateOptions: function () {
|
|
return $.metadata && $.metadata.get(this.element[0])[this.widgetName];
|
|
},
|
|
_create: function () {},
|
|
_init: function () {},
|
|
|
|
destroy: function () {
|
|
this.element.off('.' + this.widgetName).removeData(this.widgetName);
|
|
this.widget()
|
|
.off('.' + this.widgetName)
|
|
.removeAttr('aria-disabled')
|
|
.removeClass(this.widgetBaseClass + '-disabled ' + 'ui-state-disabled');
|
|
},
|
|
|
|
widget: function () {
|
|
return this.element;
|
|
},
|
|
|
|
option: function (key, value) {
|
|
var options = key;
|
|
|
|
if (arguments.length === 0) {
|
|
// don't return a reference to the internal hash
|
|
return $.extend({}, this.options);
|
|
}
|
|
|
|
if (typeof key === 'string') {
|
|
if (value === undefined) {
|
|
return this.options[key];
|
|
}
|
|
options = {};
|
|
options[key] = value;
|
|
}
|
|
|
|
this._setOptions(options);
|
|
|
|
return this;
|
|
},
|
|
_setOptions: function (options) {
|
|
var self = this;
|
|
$.each(options, function (key, value) {
|
|
self._setOption(key, value);
|
|
});
|
|
|
|
return this;
|
|
},
|
|
_setOption: function (key, value) {
|
|
this.options[key] = value;
|
|
|
|
if (key === 'disabled') {
|
|
this.widget()
|
|
[value ? 'addClass' : 'removeClass'](
|
|
this.widgetBaseClass + '-disabled' + ' ' + 'ui-state-disabled'
|
|
)
|
|
.attr('aria-disabled', value);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
enable: function () {
|
|
return this._setOption('disabled', false);
|
|
},
|
|
disable: function () {
|
|
return this._setOption('disabled', true);
|
|
},
|
|
|
|
_trigger: function (type, event, data) {
|
|
var prop,
|
|
orig,
|
|
callback = this.options[type];
|
|
|
|
data = data || {};
|
|
event = $.Event(event);
|
|
event.type = (
|
|
type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type
|
|
).toLowerCase();
|
|
// the original event may come from any element
|
|
// so we need to reset the target on the new event
|
|
event.target = this.element[0];
|
|
|
|
// copy original event properties over to the new event
|
|
orig = event.originalEvent;
|
|
if (orig) {
|
|
for (prop in orig) {
|
|
if (!(prop in event)) {
|
|
event[prop] = orig[prop];
|
|
}
|
|
}
|
|
}
|
|
|
|
this.element.trigger(event, data);
|
|
|
|
return !(
|
|
($.isFunction(callback) &&
|
|
callback.call(this.element[0], event, data) === false) ||
|
|
event.isDefaultPrevented()
|
|
);
|
|
},
|
|
};
|
|
})(jQuery);
|
|
/*!
|
|
* jQuery UI Accordion 1.8.22
|
|
*
|
|
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
* http://jquery.org/license
|
|
*
|
|
* http://docs.jquery.com/UI/Accordion
|
|
*
|
|
* Depends:
|
|
* jquery.ui.core.js
|
|
* jquery.ui.widget.js
|
|
*/
|
|
(function ($, undefined) {
|
|
$.widget('ui.accordion', {
|
|
options: {
|
|
active: 0,
|
|
animated: 'slide',
|
|
autoHeight: true,
|
|
clearStyle: false,
|
|
collapsible: false,
|
|
event: 'click',
|
|
fillSpace: false,
|
|
header: '> li > :first-child,> :not(li):even',
|
|
icons: {
|
|
header: 'ui-icon-triangle-1-e',
|
|
headerSelected: 'ui-icon-triangle-1-s',
|
|
},
|
|
navigation: false,
|
|
navigationFilter: function () {
|
|
return this.href.toLowerCase() === location.href.toLowerCase();
|
|
},
|
|
},
|
|
|
|
_create: function () {
|
|
var self = this,
|
|
options = self.options;
|
|
|
|
self.running = 0;
|
|
|
|
self.element
|
|
.addClass('ui-accordion ui-widget ui-helper-reset')
|
|
// in lack of child-selectors in CSS
|
|
// we need to mark top-LIs in a UL-accordion for some IE-fix
|
|
.children('li')
|
|
.addClass('ui-accordion-li-fix');
|
|
|
|
self.headers = self.element
|
|
.find(options.header)
|
|
.addClass(
|
|
'ui-accordion-header ui-helper-reset ui-state-default ui-corner-all'
|
|
)
|
|
.bind('mouseenter.accordion', function () {
|
|
if (options.disabled) {
|
|
return;
|
|
}
|
|
$(this).addClass('ui-state-hover');
|
|
})
|
|
.bind('mouseleave.accordion', function () {
|
|
if (options.disabled) {
|
|
return;
|
|
}
|
|
$(this).removeClass('ui-state-hover');
|
|
})
|
|
.bind('focus.accordion', function () {
|
|
if (options.disabled) {
|
|
return;
|
|
}
|
|
$(this).addClass('ui-state-focus');
|
|
})
|
|
.bind('blur.accordion', function () {
|
|
if (options.disabled) {
|
|
return;
|
|
}
|
|
$(this).removeClass('ui-state-focus');
|
|
});
|
|
|
|
self.headers
|
|
.next()
|
|
.addClass(
|
|
'ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom'
|
|
);
|
|
|
|
if (options.navigation) {
|
|
var current = self.element
|
|
.find('a')
|
|
.filter(options.navigationFilter)
|
|
.eq(0);
|
|
if (current.length) {
|
|
var header = current.closest('.ui-accordion-header');
|
|
if (header.length) {
|
|
// anchor within header
|
|
self.active = header;
|
|
} else {
|
|
// anchor within content
|
|
self.active = current.closest('.ui-accordion-content').prev();
|
|
}
|
|
}
|
|
}
|
|
|
|
self.active = self
|
|
._findActive(self.active || options.active)
|
|
.addClass('ui-state-default ui-state-active')
|
|
.toggleClass('ui-corner-all')
|
|
.toggleClass('ui-corner-top');
|
|
self.active.next().addClass('ui-accordion-content-active');
|
|
|
|
self._createIcons();
|
|
self.on('resize');
|
|
|
|
// ARIA
|
|
self.element.attr('role', 'tablist');
|
|
|
|
self.headers
|
|
.attr('role', 'tab')
|
|
.bind('keydown.accordion', function (event) {
|
|
return self._keydown(event);
|
|
})
|
|
.next()
|
|
.attr('role', 'tabpanel');
|
|
|
|
self.headers
|
|
.not(self.active || '')
|
|
.attr({
|
|
'aria-expanded': 'false',
|
|
'aria-selected': 'false',
|
|
tabIndex: -1,
|
|
})
|
|
.next()
|
|
.hide();
|
|
|
|
// make sure at least one header is in the tab order
|
|
if (!self.active.length) {
|
|
self.headers.eq(0).attr('tabIndex', 0);
|
|
} else {
|
|
self.active.attr({
|
|
'aria-expanded': 'true',
|
|
'aria-selected': 'true',
|
|
tabIndex: 0,
|
|
});
|
|
}
|
|
|
|
// only need links in tab order for Safari
|
|
if (!$.browser.safari) {
|
|
self.headers.find('a').attr('tabIndex', -1);
|
|
}
|
|
|
|
if (options.event) {
|
|
self.headers.bind(
|
|
options.event.split(' ').join('.accordion ') + '.accordion',
|
|
function (event) {
|
|
self._clickHandler.call(self, event, this);
|
|
event.preventDefault();
|
|
}
|
|
);
|
|
}
|
|
},
|
|
|
|
_createIcons: function () {
|
|
var options = this.options;
|
|
if (options.icons) {
|
|
$('<span></span>')
|
|
.addClass('ui-icon ' + options.icons.header)
|
|
.prependTo(this.headers);
|
|
this.active
|
|
.children('.ui-icon')
|
|
.toggleClass(options.icons.header)
|
|
.toggleClass(options.icons.headerSelected);
|
|
this.element.addClass('ui-accordion-icons');
|
|
}
|
|
},
|
|
|
|
_destroyIcons: function () {
|
|
this.headers.children('.ui-icon').remove();
|
|
this.element.removeClass('ui-accordion-icons');
|
|
},
|
|
|
|
destroy: function () {
|
|
var options = this.options;
|
|
|
|
this.element
|
|
.removeClass('ui-accordion ui-widget ui-helper-reset')
|
|
.removeAttr('role');
|
|
|
|
this.headers
|
|
.off('.accordion')
|
|
.removeClass(
|
|
'ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top'
|
|
)
|
|
.removeAttr('role')
|
|
.removeAttr('aria-expanded')
|
|
.removeAttr('aria-selected')
|
|
.removeAttr('tabIndex');
|
|
|
|
this.headers.find('a').removeAttr('tabIndex');
|
|
this._destroyIcons();
|
|
var contents = this.headers
|
|
.next()
|
|
.css('display', '')
|
|
.removeAttr('role')
|
|
.removeClass(
|
|
'ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled'
|
|
);
|
|
if (options.autoHeight || options.fillHeight) {
|
|
contents.css('height', '');
|
|
}
|
|
|
|
return $.Widget.prototype.destroy.call(this);
|
|
},
|
|
|
|
_setOption: function (key, value) {
|
|
$.Widget.prototype._setOption.apply(this, arguments);
|
|
|
|
if (key == 'active') {
|
|
this.activate(value);
|
|
}
|
|
if (key == 'icons') {
|
|
this._destroyIcons();
|
|
if (value) {
|
|
this._createIcons();
|
|
}
|
|
}
|
|
// #5332 - opacity doesn't cascade to positioned elements in IE
|
|
// so we need to add the disabled class to the headers and panels
|
|
if (key == 'disabled') {
|
|
this.headers
|
|
.add(this.headers.next())
|
|
[value ? 'addClass' : 'removeClass'](
|
|
'ui-accordion-disabled ui-state-disabled'
|
|
);
|
|
}
|
|
},
|
|
|
|
_keydown: function (event) {
|
|
if (this.options.disabled || event.altKey || event.ctrlKey) {
|
|
return;
|
|
}
|
|
|
|
var keyCode = $.ui.keyCode,
|
|
length = this.headers.length,
|
|
currentIndex = this.headers.index(event.target),
|
|
toFocus = false;
|
|
|
|
switch (event.keyCode) {
|
|
case keyCode.LEFT:
|
|
case keyCode.DOWN:
|
|
toFocus = this.headers[(currentIndex + 1) % length];
|
|
break;
|
|
case keyCode.RIGHT:
|
|
case keyCode.UP:
|
|
toFocus = this.headers[(currentIndex - 1 + length) % length];
|
|
break;
|
|
case keyCode.SPACE:
|
|
case keyCode.ENTER:
|
|
this._clickHandler({ target: event.target }, event.target);
|
|
event.preventDefault();
|
|
}
|
|
|
|
if (toFocus) {
|
|
$(event.target).attr('tabIndex', -1);
|
|
$(toFocus).attr('tabIndex', 0);
|
|
toFocus.focus();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
resize: function () {
|
|
var options = this.options,
|
|
maxHeight;
|
|
|
|
if (options.fillSpace) {
|
|
if ($.browser.msie) {
|
|
var defOverflow = this.element.parent().css('overflow');
|
|
this.element.parent().css('overflow', 'hidden');
|
|
}
|
|
maxHeight = this.element.parent().height();
|
|
if ($.browser.msie) {
|
|
this.element.parent().css('overflow', defOverflow);
|
|
}
|
|
|
|
this.headers.each(function () {
|
|
maxHeight -= $(this).outerHeight(true);
|
|
});
|
|
|
|
this.headers
|
|
.next()
|
|
.each(function () {
|
|
$(this).height(
|
|
Math.max(0, maxHeight - $(this).innerHeight() + $(this).height())
|
|
);
|
|
})
|
|
.css('overflow', 'auto');
|
|
} else if (options.autoHeight) {
|
|
maxHeight = 0;
|
|
this.headers
|
|
.next()
|
|
.each(function () {
|
|
maxHeight = Math.max(maxHeight, $(this).height('').height());
|
|
})
|
|
.height(maxHeight);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
activate: function (index) {
|
|
// TODO this gets called on init, changing the option without an explicit call for that
|
|
this.options.active = index;
|
|
// call clickHandler with custom event
|
|
var active = this._findActive(index)[0];
|
|
this._clickHandler({ target: active }, active);
|
|
|
|
return this;
|
|
},
|
|
|
|
_findActive: function (selector) {
|
|
return selector
|
|
? typeof selector === 'number'
|
|
? this.headers.filter(':eq(' + selector + ')')
|
|
: this.headers.not(this.headers.not(selector))
|
|
: selector === false
|
|
? $([])
|
|
: this.headers.filter(':eq(0)');
|
|
},
|
|
|
|
// TODO isn't event.target enough? why the separate target argument?
|
|
_clickHandler: function (event, target) {
|
|
var options = this.options;
|
|
if (options.disabled) {
|
|
return;
|
|
}
|
|
|
|
// called only when using activate(false) to close all parts programmatically
|
|
if (!event.target) {
|
|
if (!options.collapsible) {
|
|
return;
|
|
}
|
|
this.active
|
|
.removeClass('ui-state-active ui-corner-top')
|
|
.addClass('ui-state-default ui-corner-all')
|
|
.children('.ui-icon')
|
|
.removeClass(options.icons.headerSelected)
|
|
.addClass(options.icons.header);
|
|
this.active.next().addClass('ui-accordion-content-active');
|
|
var toHide = this.active.next(),
|
|
data = {
|
|
options: options,
|
|
newHeader: $([]),
|
|
oldHeader: options.active,
|
|
newContent: $([]),
|
|
oldContent: toHide,
|
|
},
|
|
toShow = (this.active = $([]));
|
|
this._toggle(toShow, toHide, data);
|
|
return;
|
|
}
|
|
|
|
// get the click target
|
|
var clicked = $(event.currentTarget || target),
|
|
clickedIsActive = clicked[0] === this.active[0];
|
|
|
|
// TODO the option is changed, is that correct?
|
|
// TODO if it is correct, shouldn't that happen after determining that the click is valid?
|
|
options.active =
|
|
options.collapsible && clickedIsActive
|
|
? false
|
|
: this.headers.index(clicked);
|
|
|
|
// if animations are still active, or the active header is the target, ignore click
|
|
if (this.running || (!options.collapsible && clickedIsActive)) {
|
|
return;
|
|
}
|
|
|
|
// find elements to show and hide
|
|
var active = this.active,
|
|
toShow = clicked.next(),
|
|
toHide = this.active.next(),
|
|
data = {
|
|
options: options,
|
|
newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
|
|
oldHeader: this.active,
|
|
newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
|
|
oldContent: toHide,
|
|
},
|
|
down =
|
|
this.headers.index(this.active[0]) > this.headers.index(clicked[0]);
|
|
|
|
// when the call to ._toggle() comes after the class changes
|
|
// it causes a very odd bug in IE 8 (see #6720)
|
|
this.active = clickedIsActive ? $([]) : clicked;
|
|
this._toggle(toShow, toHide, data, clickedIsActive, down);
|
|
|
|
// switch classes
|
|
active
|
|
.removeClass('ui-state-active ui-corner-top')
|
|
.addClass('ui-state-default ui-corner-all')
|
|
.children('.ui-icon')
|
|
.removeClass(options.icons.headerSelected)
|
|
.addClass(options.icons.header);
|
|
if (!clickedIsActive) {
|
|
clicked
|
|
.removeClass('ui-state-default ui-corner-all')
|
|
.addClass('ui-state-active ui-corner-top')
|
|
.children('.ui-icon')
|
|
.removeClass(options.icons.header)
|
|
.addClass(options.icons.headerSelected);
|
|
clicked.next().addClass('ui-accordion-content-active');
|
|
}
|
|
|
|
return;
|
|
},
|
|
|
|
_toggle: function (toShow, toHide, data, clickedIsActive, down) {
|
|
var self = this,
|
|
options = self.options;
|
|
|
|
self.toShow = toShow;
|
|
self.toHide = toHide;
|
|
self.data = data;
|
|
|
|
var complete = function () {
|
|
if (!self) {
|
|
return;
|
|
}
|
|
return self._completed.apply(self, arguments);
|
|
};
|
|
|
|
// trigger changestart event
|
|
self._trigger('changestart', null, self.data);
|
|
|
|
// count elements to animate
|
|
self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
|
|
|
|
if (options.animated) {
|
|
var animOptions = {};
|
|
|
|
if (options.collapsible && clickedIsActive) {
|
|
animOptions = {
|
|
toShow: $([]),
|
|
toHide: toHide,
|
|
complete: complete,
|
|
down: down,
|
|
autoHeight: options.autoHeight || options.fillSpace,
|
|
};
|
|
} else {
|
|
animOptions = {
|
|
toShow: toShow,
|
|
toHide: toHide,
|
|
complete: complete,
|
|
down: down,
|
|
autoHeight: options.autoHeight || options.fillSpace,
|
|
};
|
|
}
|
|
|
|
if (!options.proxied) {
|
|
options.proxied = options.animated;
|
|
}
|
|
|
|
if (!options.proxiedDuration) {
|
|
options.proxiedDuration = options.duration;
|
|
}
|
|
|
|
options.animated = $.isFunction(options.proxied)
|
|
? options.proxied(animOptions)
|
|
: options.proxied;
|
|
|
|
options.duration = $.isFunction(options.proxiedDuration)
|
|
? options.proxiedDuration(animOptions)
|
|
: options.proxiedDuration;
|
|
|
|
var animations = $.ui.accordion.animations,
|
|
duration = options.duration,
|
|
easing = options.animated;
|
|
|
|
if (easing && !animations[easing] && !$.easing[easing]) {
|
|
easing = 'slide';
|
|
}
|
|
if (!animations[easing]) {
|
|
animations[easing] = function (options) {
|
|
this.slide(options, {
|
|
easing: easing,
|
|
duration: duration || 700,
|
|
});
|
|
};
|
|
}
|
|
|
|
animations[easing](animOptions);
|
|
} else {
|
|
if (options.collapsible && clickedIsActive) {
|
|
toShow.toggle();
|
|
} else {
|
|
toHide.hide();
|
|
toShow.show();
|
|
}
|
|
|
|
complete(true);
|
|
}
|
|
|
|
// TODO assert that the blur and focus triggers are really necessary, remove otherwise
|
|
toHide
|
|
.prev()
|
|
.attr({
|
|
'aria-expanded': 'false',
|
|
'aria-selected': 'false',
|
|
tabIndex: -1,
|
|
})
|
|
.blur();
|
|
toShow
|
|
.prev()
|
|
.attr({
|
|
'aria-expanded': 'true',
|
|
'aria-selected': 'true',
|
|
tabIndex: 0,
|
|
})
|
|
.focus();
|
|
},
|
|
|
|
_completed: function (cancel) {
|
|
this.running = cancel ? 0 : --this.running;
|
|
if (this.running) {
|
|
return;
|
|
}
|
|
|
|
if (this.options.clearStyle) {
|
|
this.toShow.add(this.toHide).css({
|
|
height: '',
|
|
overflow: '',
|
|
});
|
|
}
|
|
|
|
// other classes are removed before the animation; this one needs to stay until completed
|
|
this.toHide.removeClass('ui-accordion-content-active');
|
|
// Work around for rendering bug in IE (#5421)
|
|
if (this.toHide.length) {
|
|
this.toHide.parent()[0].className = this.toHide.parent()[0].className;
|
|
}
|
|
|
|
this._trigger('change', null, this.data);
|
|
},
|
|
});
|
|
|
|
$.extend($.ui.accordion, {
|
|
version: '1.8.22',
|
|
animations: {
|
|
slide: function (options, additions) {
|
|
options = $.extend(
|
|
{
|
|
easing: 'swing',
|
|
duration: 300,
|
|
},
|
|
options,
|
|
additions
|
|
);
|
|
if (!options.toHide.size()) {
|
|
options.toShow.animate(
|
|
{
|
|
height: 'show',
|
|
paddingTop: 'show',
|
|
paddingBottom: 'show',
|
|
},
|
|
options
|
|
);
|
|
return;
|
|
}
|
|
if (!options.toShow.size()) {
|
|
options.toHide.animate(
|
|
{
|
|
height: 'hide',
|
|
paddingTop: 'hide',
|
|
paddingBottom: 'hide',
|
|
},
|
|
options
|
|
);
|
|
return;
|
|
}
|
|
var overflow = options.toShow.css('overflow'),
|
|
percentDone = 0,
|
|
showProps = {},
|
|
hideProps = {},
|
|
fxAttrs = ['height', 'paddingTop', 'paddingBottom'],
|
|
originalWidth;
|
|
// fix width before calculating height of hidden element
|
|
var s = options.toShow;
|
|
originalWidth = s[0].style.width;
|
|
s.width(
|
|
s.parent().width() -
|
|
parseFloat(s.css('paddingLeft')) -
|
|
parseFloat(s.css('paddingRight')) -
|
|
(parseFloat(s.css('borderLeftWidth')) || 0) -
|
|
(parseFloat(s.css('borderRightWidth')) || 0)
|
|
);
|
|
|
|
$.each(fxAttrs, function (i, prop) {
|
|
hideProps[prop] = 'hide';
|
|
|
|
var parts = ('' + $.css(options.toShow[0], prop)).match(
|
|
/^([\d+-.]+)(.*)$/
|
|
);
|
|
showProps[prop] = {
|
|
value: parts[1],
|
|
unit: parts[2] || 'px',
|
|
};
|
|
});
|
|
options.toShow.css({ height: 0, overflow: 'hidden' }).show();
|
|
options.toHide
|
|
.filter(':hidden')
|
|
.each(options.complete)
|
|
.end()
|
|
.filter(':visible')
|
|
.animate(hideProps, {
|
|
step: function (now, settings) {
|
|
// only calculate the percent when animating height
|
|
// IE gets very inconsistent results when animating elements
|
|
// with small values, which is common for padding
|
|
if (settings.prop == 'height') {
|
|
percentDone =
|
|
settings.end - settings.start === 0
|
|
? 0
|
|
: (settings.now - settings.start) /
|
|
(settings.end - settings.start);
|
|
}
|
|
|
|
options.toShow[0].style[settings.prop] =
|
|
percentDone * showProps[settings.prop].value +
|
|
showProps[settings.prop].unit;
|
|
},
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
complete: function () {
|
|
if (!options.autoHeight) {
|
|
options.toShow.css('height', '');
|
|
}
|
|
options.toShow.css({
|
|
width: originalWidth,
|
|
overflow: overflow,
|
|
});
|
|
options.complete();
|
|
},
|
|
});
|
|
},
|
|
bounceslide: function (options) {
|
|
this.slide(options, {
|
|
easing: options.down ? 'easeOutBounce' : 'swing',
|
|
duration: options.down ? 1000 : 200,
|
|
});
|
|
},
|
|
},
|
|
});
|
|
})(jQuery);
|
|
/*!
|
|
* jQuery UI Tabs 1.8.22
|
|
*
|
|
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
* http://jquery.org/license
|
|
*
|
|
* http://docs.jquery.com/UI/Tabs
|
|
*
|
|
* Depends:
|
|
* jquery.ui.core.js
|
|
* jquery.ui.widget.js
|
|
*/
|
|
(function ($, undefined) {
|
|
var tabId = 0,
|
|
listId = 0;
|
|
|
|
function getNextTabId() {
|
|
return ++tabId;
|
|
}
|
|
|
|
function getNextListId() {
|
|
return ++listId;
|
|
}
|
|
|
|
$.widget('ui.tabs', {
|
|
options: {
|
|
add: null,
|
|
ajaxOptions: null,
|
|
cache: false,
|
|
cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
|
|
collapsible: false,
|
|
disable: null,
|
|
disabled: [],
|
|
enable: null,
|
|
event: 'click',
|
|
fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
|
|
idPrefix: 'ui-tabs-',
|
|
load: null,
|
|
panelTemplate: '<div></div>',
|
|
remove: null,
|
|
select: null,
|
|
show: null,
|
|
spinner: '<em>Loading…</em>',
|
|
tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>",
|
|
},
|
|
|
|
_create: function () {
|
|
this._tabify(true);
|
|
},
|
|
|
|
_setOption: function (key, value) {
|
|
if (key == 'selected') {
|
|
if (this.options.collapsible && value == this.options.selected) {
|
|
return;
|
|
}
|
|
this.select(value);
|
|
} else {
|
|
this.options[key] = value;
|
|
this._tabify();
|
|
}
|
|
},
|
|
|
|
_tabId: function (a) {
|
|
return (
|
|
(a.title &&
|
|
a.title.replace(/\s/g, '_').replace(/[^\w\u00c0-\uFFFF-]/g, '')) ||
|
|
this.options.idPrefix + getNextTabId()
|
|
);
|
|
},
|
|
|
|
_sanitizeSelector: function (hash) {
|
|
// we need this because an id may contain a ":"
|
|
return hash.replace(/:/g, '\\:');
|
|
},
|
|
|
|
_cookie: function () {
|
|
var cookie =
|
|
this.cookie ||
|
|
(this.cookie =
|
|
this.options.cookie.name || 'ui-tabs-' + getNextListId());
|
|
return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
|
|
},
|
|
|
|
_ui: function (tab, panel) {
|
|
return {
|
|
tab: tab,
|
|
panel: panel,
|
|
index: this.anchors.index(tab),
|
|
};
|
|
},
|
|
|
|
_cleanup: function () {
|
|
// restore all former loading tabs labels
|
|
this.lis
|
|
.filter('.ui-state-processing')
|
|
.removeClass('ui-state-processing')
|
|
.find('span:data(label.tabs)')
|
|
.each(function () {
|
|
var el = $(this);
|
|
el.html(el.data('label.tabs')).removeData('label.tabs');
|
|
});
|
|
},
|
|
|
|
_tabify: function (init) {
|
|
var self = this,
|
|
o = this.options,
|
|
fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
|
|
|
|
this.list = this.element.find('ol,ul').eq(0);
|
|
this.lis = $(' > li:has(a[href])', this.list);
|
|
this.anchors = this.lis.map(function () {
|
|
return $('a', this)[0];
|
|
});
|
|
this.panels = $([]);
|
|
|
|
this.anchors.each(function (i, a) {
|
|
var href = $(a).attr('href');
|
|
// For dynamically created HTML that contains a hash as href IE < 8 expands
|
|
// such href to the full page url with hash and then misinterprets tab as ajax.
|
|
// Same consideration applies for an added tab with a fragment identifier
|
|
// since a[href=#fragment-identifier] does unexpectedly not match.
|
|
// Thus normalize href attribute...
|
|
var hrefBase = href.split('#')[0],
|
|
baseEl;
|
|
if (
|
|
hrefBase &&
|
|
(hrefBase === location.toString().split('#')[0] ||
|
|
((baseEl = $('base')[0]) && hrefBase === baseEl.href))
|
|
) {
|
|
href = a.hash;
|
|
a.href = href;
|
|
}
|
|
|
|
// inline tab
|
|
if (fragmentId.test(href)) {
|
|
self.panels = self.panels.add(
|
|
self.element.find(self._sanitizeSelector(href))
|
|
);
|
|
// remote tab
|
|
// prevent loading the page itself if href is just "#"
|
|
} else if (href && href !== '#') {
|
|
// required for restore on destroy
|
|
$.data(a, 'href.tabs', href);
|
|
|
|
// TODO until #3808 is fixed strip fragment identifier from url
|
|
// (IE fails to load from such url)
|
|
$.data(a, 'load.tabs', href.replace(/#.*$/, ''));
|
|
|
|
var id = self._tabId(a);
|
|
a.href = '#' + id;
|
|
var $panel = self.element.find('#' + id);
|
|
if (!$panel.length) {
|
|
$panel = $(o.panelTemplate)
|
|
.attr('id', id)
|
|
.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
|
|
.insertAfter(self.panels[i - 1] || self.list);
|
|
$panel.data('destroy.tabs', true);
|
|
}
|
|
self.panels = self.panels.add($panel);
|
|
// invalid tab href
|
|
} else {
|
|
o.disabled.push(i);
|
|
}
|
|
});
|
|
|
|
// initialization from scratch
|
|
if (init) {
|
|
// attach necessary classes for styling
|
|
this.element.addClass(
|
|
'ui-tabs ui-widget ui-widget-content ui-corner-all'
|
|
);
|
|
this.list.addClass(
|
|
'ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all'
|
|
);
|
|
this.lis.addClass('ui-state-default ui-corner-top');
|
|
this.panels.addClass(
|
|
'ui-tabs-panel ui-widget-content ui-corner-bottom'
|
|
);
|
|
|
|
// Selected tab
|
|
// use "selected" option or try to retrieve:
|
|
// 1. from fragment identifier in url
|
|
// 2. from cookie
|
|
// 3. from selected class attribute on <li>
|
|
if (o.selected === undefined) {
|
|
if (location.hash) {
|
|
this.anchors.each(function (i, a) {
|
|
if (a.hash == location.hash) {
|
|
o.selected = i;
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
if (typeof o.selected !== 'number' && o.cookie) {
|
|
o.selected = parseInt(self._cookie(), 10);
|
|
}
|
|
if (
|
|
typeof o.selected !== 'number' &&
|
|
this.lis.filter('.ui-tabs-selected').length
|
|
) {
|
|
o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
|
|
}
|
|
o.selected = o.selected || (this.lis.length ? 0 : -1);
|
|
} else if (o.selected === null) {
|
|
// usage of null is deprecated, TODO remove in next release
|
|
o.selected = -1;
|
|
}
|
|
|
|
// sanity check - default to first tab...
|
|
o.selected =
|
|
(o.selected >= 0 && this.anchors[o.selected]) || o.selected < 0
|
|
? o.selected
|
|
: 0;
|
|
|
|
// Take disabling tabs via class attribute from HTML
|
|
// into account and update option properly.
|
|
// A selected tab cannot become disabled.
|
|
o.disabled = $.unique(
|
|
o.disabled.concat(
|
|
$.map(this.lis.filter('.ui-state-disabled'), function (n, i) {
|
|
return self.lis.index(n);
|
|
})
|
|
)
|
|
).sort();
|
|
|
|
if ($.inArray(o.selected, o.disabled) != -1) {
|
|
o.disabled.splice($.inArray(o.selected, o.disabled), 1);
|
|
}
|
|
|
|
// highlight selected tab
|
|
this.panels.addClass('ui-tabs-hide');
|
|
this.lis.removeClass('ui-tabs-selected ui-state-active');
|
|
// check for length avoids error when initializing empty list
|
|
if (o.selected >= 0 && this.anchors.length) {
|
|
self.element
|
|
.find(self._sanitizeSelector(self.anchors[o.selected].hash))
|
|
.removeClass('ui-tabs-hide');
|
|
this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active');
|
|
|
|
// seems to be expected behavior that the show callback is fired
|
|
self.element.queue('tabs', function () {
|
|
self._trigger(
|
|
'show',
|
|
null,
|
|
self._ui(
|
|
self.anchors[o.selected],
|
|
self.element.find(
|
|
self._sanitizeSelector(self.anchors[o.selected].hash)
|
|
)[0]
|
|
)
|
|
);
|
|
});
|
|
|
|
this.load(o.selected);
|
|
}
|
|
|
|
// clean up to avoid memory leaks in certain versions of IE 6
|
|
// TODO: namespace this event
|
|
$(window).bind('unload', function () {
|
|
self.lis.add(self.anchors).off('.tabs');
|
|
self.lis = self.anchors = self.panels = null;
|
|
});
|
|
// update selected after add/remove
|
|
} else {
|
|
o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
|
|
}
|
|
|
|
// update collapsible
|
|
// TODO: use .toggleClass()
|
|
this.element[o.collapsible ? 'addClass' : 'removeClass'](
|
|
'ui-tabs-collapsible'
|
|
);
|
|
|
|
// set or update cookie after init and add/remove respectively
|
|
if (o.cookie) {
|
|
this._cookie(o.selected, o.cookie);
|
|
}
|
|
|
|
// disable tabs
|
|
for (var i = 0, li; (li = this.lis[i]); i++) {
|
|
$(li)[
|
|
$.inArray(i, o.disabled) != -1 &&
|
|
// TODO: use .toggleClass()
|
|
!$(li).hasClass('ui-tabs-selected')
|
|
? 'addClass'
|
|
: 'removeClass'
|
|
]('ui-state-disabled');
|
|
}
|
|
|
|
// reset cache if switching from cached to not cached
|
|
if (o.cache === false) {
|
|
this.anchors.removeData('cache.tabs');
|
|
}
|
|
|
|
// remove all handlers before, tabify may run on existing tabs after add or option change
|
|
this.lis.add(this.anchors).off('.tabs');
|
|
|
|
if (o.event !== 'mouseover') {
|
|
var addState = function (state, el) {
|
|
if (el.is(':not(.ui-state-disabled)')) {
|
|
el.addClass('ui-state-' + state);
|
|
}
|
|
};
|
|
var removeState = function (state, el) {
|
|
el.removeClass('ui-state-' + state);
|
|
};
|
|
this.lis.bind('mouseover.tabs', function () {
|
|
addState('hover', $(this));
|
|
});
|
|
this.lis.bind('mouseout.tabs', function () {
|
|
removeState('hover', $(this));
|
|
});
|
|
this.anchors.bind('focus.tabs', function () {
|
|
addState('focus', $(this).closest('li'));
|
|
});
|
|
this.anchors.bind('blur.tabs', function () {
|
|
removeState('focus', $(this).closest('li'));
|
|
});
|
|
}
|
|
|
|
// set up animations
|
|
var hideFx, showFx;
|
|
if (o.fx) {
|
|
if ($.isArray(o.fx)) {
|
|
hideFx = o.fx[0];
|
|
showFx = o.fx[1];
|
|
} else {
|
|
hideFx = showFx = o.fx;
|
|
}
|
|
}
|
|
|
|
// Reset certain styles right over from animation
|
|
// and prevent IE's ClearType bug...
|
|
function resetStyle($el, fx) {
|
|
$el.css('display', '');
|
|
if (!$.support.opacity && fx.opacity) {
|
|
$el[0].style.removeAttribute('filter');
|
|
}
|
|
}
|
|
|
|
// Show a tab...
|
|
var showTab = showFx
|
|
? function (clicked, $show) {
|
|
$(clicked)
|
|
.closest('li')
|
|
.addClass('ui-tabs-selected ui-state-active');
|
|
$show
|
|
.hide()
|
|
.removeClass('ui-tabs-hide') // avoid flicker that way
|
|
.animate(showFx, showFx.duration || 'normal', function () {
|
|
resetStyle($show, showFx);
|
|
self._trigger('show', null, self._ui(clicked, $show[0]));
|
|
});
|
|
}
|
|
: function (clicked, $show) {
|
|
$(clicked)
|
|
.closest('li')
|
|
.addClass('ui-tabs-selected ui-state-active');
|
|
$show.removeClass('ui-tabs-hide');
|
|
self._trigger('show', null, self._ui(clicked, $show[0]));
|
|
};
|
|
|
|
// Hide a tab, $show is optional...
|
|
var hideTab = hideFx
|
|
? function (clicked, $hide) {
|
|
$hide.animate(hideFx, hideFx.duration || 'normal', function () {
|
|
self.lis.removeClass('ui-tabs-selected ui-state-active');
|
|
$hide.addClass('ui-tabs-hide');
|
|
resetStyle($hide, hideFx);
|
|
self.element.dequeue('tabs');
|
|
});
|
|
}
|
|
: function (clicked, $hide, $show) {
|
|
self.lis.removeClass('ui-tabs-selected ui-state-active');
|
|
$hide.addClass('ui-tabs-hide');
|
|
self.element.dequeue('tabs');
|
|
};
|
|
|
|
// attach tab event handler, unbind to avoid duplicates from former tabifying...
|
|
this.anchors.bind(o.event + '.tabs', function () {
|
|
var el = this,
|
|
$li = $(el).closest('li'),
|
|
$hide = self.panels.filter(':not(.ui-tabs-hide)'),
|
|
$show = self.element.find(self._sanitizeSelector(el.hash));
|
|
|
|
// If tab is already selected and not collapsible or tab disabled or
|
|
// or is already loading or click callback returns false stop here.
|
|
// Check if click handler returns false last so that it is not executed
|
|
// for a disabled or loading tab!
|
|
if (
|
|
($li.hasClass('ui-tabs-selected') && !o.collapsible) ||
|
|
$li.hasClass('ui-state-disabled') ||
|
|
$li.hasClass('ui-state-processing') ||
|
|
self.panels.filter(':animated').length ||
|
|
self._trigger('select', null, self._ui(this, $show[0])) === false
|
|
) {
|
|
this.blur();
|
|
return false;
|
|
}
|
|
|
|
o.selected = self.anchors.index(this);
|
|
|
|
self.abort();
|
|
|
|
// if tab may be closed
|
|
if (o.collapsible) {
|
|
if ($li.hasClass('ui-tabs-selected')) {
|
|
o.selected = -1;
|
|
|
|
if (o.cookie) {
|
|
self._cookie(o.selected, o.cookie);
|
|
}
|
|
|
|
self.element
|
|
.queue('tabs', function () {
|
|
hideTab(el, $hide);
|
|
})
|
|
.dequeue('tabs');
|
|
|
|
this.blur();
|
|
return false;
|
|
} else if (!$hide.length) {
|
|
if (o.cookie) {
|
|
self._cookie(o.selected, o.cookie);
|
|
}
|
|
|
|
self.element.queue('tabs', function () {
|
|
showTab(el, $show);
|
|
});
|
|
|
|
// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
|
|
self.load(self.anchors.index(this));
|
|
|
|
this.blur();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (o.cookie) {
|
|
self._cookie(o.selected, o.cookie);
|
|
}
|
|
|
|
// show new tab
|
|
if ($show.length) {
|
|
if ($hide.length) {
|
|
self.element.queue('tabs', function () {
|
|
hideTab(el, $hide);
|
|
});
|
|
}
|
|
self.element.queue('tabs', function () {
|
|
showTab(el, $show);
|
|
});
|
|
|
|
self.load(self.anchors.index(this));
|
|
} else {
|
|
throw 'jQuery UI Tabs: Mismatching fragment identifier.';
|
|
}
|
|
|
|
// Prevent IE from keeping other link focussed when using the back button
|
|
// and remove dotted border from clicked link. This is controlled via CSS
|
|
// in modern browsers; blur() removes focus from address bar in Firefox
|
|
// which can become a usability and annoying problem with tabs('rotate').
|
|
if ($.browser.msie) {
|
|
this.blur();
|
|
}
|
|
});
|
|
|
|
// disable click in any case
|
|
this.anchors.bind('click.tabs', function () {
|
|
return false;
|
|
});
|
|
},
|
|
|
|
_getIndex: function (index) {
|
|
// meta-function to give users option to provide a href string instead of a numerical index.
|
|
// also sanitizes numerical indexes to valid values.
|
|
if (typeof index == 'string') {
|
|
index = this.anchors.index(
|
|
this.anchors.filter("[href$='" + index + "']")
|
|
);
|
|
}
|
|
|
|
return index;
|
|
},
|
|
|
|
destroy: function () {
|
|
var o = this.options;
|
|
|
|
this.abort();
|
|
|
|
this.element
|
|
.off('.tabs')
|
|
.removeClass(
|
|
'ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible'
|
|
)
|
|
.removeData('tabs');
|
|
|
|
this.list.removeClass(
|
|
'ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all'
|
|
);
|
|
|
|
this.anchors.each(function () {
|
|
var href = $.data(this, 'href.tabs');
|
|
if (href) {
|
|
this.href = href;
|
|
}
|
|
var $this = $(this).off('.tabs');
|
|
$.each(['href', 'load', 'cache'], function (i, prefix) {
|
|
$this.removeData(prefix + '.tabs');
|
|
});
|
|
});
|
|
|
|
this.lis
|
|
.off('.tabs')
|
|
.add(this.panels)
|
|
.each(function () {
|
|
if ($.data(this, 'destroy.tabs')) {
|
|
$(this).remove();
|
|
} else {
|
|
$(this).removeClass(
|
|
[
|
|
'ui-state-default',
|
|
'ui-corner-top',
|
|
'ui-tabs-selected',
|
|
'ui-state-active',
|
|
'ui-state-hover',
|
|
'ui-state-focus',
|
|
'ui-state-disabled',
|
|
'ui-tabs-panel',
|
|
'ui-widget-content',
|
|
'ui-corner-bottom',
|
|
'ui-tabs-hide',
|
|
].join(' ')
|
|
);
|
|
}
|
|
});
|
|
|
|
if (o.cookie) {
|
|
this._cookie(null, o.cookie);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
add: function (url, label, index) {
|
|
if (index === undefined) {
|
|
index = this.anchors.length;
|
|
}
|
|
|
|
var self = this,
|
|
o = this.options,
|
|
$li = $(
|
|
o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label)
|
|
),
|
|
id = !url.indexOf('#')
|
|
? url.replace('#', '')
|
|
: this._tabId($('a', $li)[0]);
|
|
|
|
$li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);
|
|
|
|
// try to find an existing element before creating a new one
|
|
var $panel = self.element.find('#' + id);
|
|
if (!$panel.length) {
|
|
$panel = $(o.panelTemplate).attr('id', id).data('destroy.tabs', true);
|
|
}
|
|
$panel.addClass(
|
|
'ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide'
|
|
);
|
|
|
|
if (index >= this.lis.length) {
|
|
$li.appendTo(this.list);
|
|
$panel.appendTo(this.list[0].parentNode);
|
|
} else {
|
|
$li.insertBefore(this.lis[index]);
|
|
$panel.insertBefore(this.panels[index]);
|
|
}
|
|
|
|
o.disabled = $.map(o.disabled, function (n, i) {
|
|
return n >= index ? ++n : n;
|
|
});
|
|
|
|
this._tabify();
|
|
|
|
if (this.anchors.length == 1) {
|
|
o.selected = 0;
|
|
$li.addClass('ui-tabs-selected ui-state-active');
|
|
$panel.removeClass('ui-tabs-hide');
|
|
this.element.queue('tabs', function () {
|
|
self._trigger(
|
|
'show',
|
|
null,
|
|
self._ui(self.anchors[0], self.panels[0])
|
|
);
|
|
});
|
|
|
|
this.load(0);
|
|
}
|
|
|
|
this._trigger(
|
|
'add',
|
|
null,
|
|
this._ui(this.anchors[index], this.panels[index])
|
|
);
|
|
return this;
|
|
},
|
|
|
|
remove: function (index) {
|
|
index = this._getIndex(index);
|
|
var o = this.options,
|
|
$li = this.lis.eq(index).remove(),
|
|
$panel = this.panels.eq(index).remove();
|
|
|
|
// If selected tab was removed focus tab to the left or
|
|
// in case the last tab was removed the tab to the right.
|
|
if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) {
|
|
this.select(index + (index + 1 < this.anchors.length ? 1 : -1));
|
|
}
|
|
|
|
o.disabled = $.map(
|
|
$.grep(o.disabled, function (n, i) {
|
|
return n != index;
|
|
}),
|
|
function (n, i) {
|
|
return n >= index ? --n : n;
|
|
}
|
|
);
|
|
|
|
this._tabify();
|
|
|
|
this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
|
|
return this;
|
|
},
|
|
|
|
enable: function (index) {
|
|
index = this._getIndex(index);
|
|
var o = this.options;
|
|
if ($.inArray(index, o.disabled) == -1) {
|
|
return;
|
|
}
|
|
|
|
this.lis.eq(index).removeClass('ui-state-disabled');
|
|
o.disabled = $.grep(o.disabled, function (n, i) {
|
|
return n != index;
|
|
});
|
|
|
|
this._trigger(
|
|
'enable',
|
|
null,
|
|
this._ui(this.anchors[index], this.panels[index])
|
|
);
|
|
return this;
|
|
},
|
|
|
|
disable: function (index) {
|
|
index = this._getIndex(index);
|
|
var self = this,
|
|
o = this.options;
|
|
// cannot disable already selected tab
|
|
if (index != o.selected) {
|
|
this.lis.eq(index).addClass('ui-state-disabled');
|
|
|
|
o.disabled.push(index);
|
|
o.disabled.sort();
|
|
|
|
this._trigger(
|
|
'disable',
|
|
null,
|
|
this._ui(this.anchors[index], this.panels[index])
|
|
);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
select: function (index) {
|
|
index = this._getIndex(index);
|
|
if (index == -1) {
|
|
if (this.options.collapsible && this.options.selected != -1) {
|
|
index = this.options.selected;
|
|
} else {
|
|
return this;
|
|
}
|
|
}
|
|
this.anchors.eq(index).trigger(this.options.event + '.tabs');
|
|
return this;
|
|
},
|
|
|
|
load: function (index) {
|
|
index = this._getIndex(index);
|
|
var self = this,
|
|
o = this.options,
|
|
a = this.anchors.eq(index)[0],
|
|
url = $.data(a, 'load.tabs');
|
|
|
|
this.abort();
|
|
|
|
// not remote or from cache
|
|
if (
|
|
!url ||
|
|
(this.element.queue('tabs').length !== 0 && $.data(a, 'cache.tabs'))
|
|
) {
|
|
this.element.dequeue('tabs');
|
|
return;
|
|
}
|
|
|
|
// load remote from here on
|
|
this.lis.eq(index).addClass('ui-state-processing');
|
|
|
|
if (o.spinner) {
|
|
var span = $('span', a);
|
|
span.data('label.tabs', span.html()).html(o.spinner);
|
|
}
|
|
|
|
this.xhr = $.ajax(
|
|
$.extend({}, o.ajaxOptions, {
|
|
url: url,
|
|
success: function (r, s) {
|
|
self.element.find(self._sanitizeSelector(a.hash)).html(r);
|
|
|
|
// take care of tab labels
|
|
self._cleanup();
|
|
|
|
if (o.cache) {
|
|
$.data(a, 'cache.tabs', true);
|
|
}
|
|
|
|
self._trigger(
|
|
'load',
|
|
null,
|
|
self._ui(self.anchors[index], self.panels[index])
|
|
);
|
|
try {
|
|
o.ajaxOptions.success(r, s);
|
|
} catch (e) {}
|
|
},
|
|
error: function (xhr, s, e) {
|
|
// take care of tab labels
|
|
self._cleanup();
|
|
|
|
self._trigger(
|
|
'load',
|
|
null,
|
|
self._ui(self.anchors[index], self.panels[index])
|
|
);
|
|
try {
|
|
// Passing index avoid a race condition when this method is
|
|
// called after the user has selected another tab.
|
|
// Pass the anchor that initiated this request allows
|
|
// loadError to manipulate the tab content panel via $(a.hash)
|
|
o.ajaxOptions.error(xhr, s, index, a);
|
|
} catch (e) {}
|
|
},
|
|
})
|
|
);
|
|
|
|
// last, so that load event is fired before show...
|
|
self.element.dequeue('tabs');
|
|
|
|
return this;
|
|
},
|
|
|
|
abort: function () {
|
|
// stop possibly running animations
|
|
this.element.queue([]);
|
|
this.panels.stop(false, true);
|
|
|
|
// "tabs" queue must not contain more than two elements,
|
|
// which are the callbacks for the latest clicked tab...
|
|
this.element.queue('tabs', this.element.queue('tabs').splice(-2, 2));
|
|
|
|
// terminate pending requests from other tabs
|
|
if (this.xhr) {
|
|
this.xhr.abort();
|
|
delete this.xhr;
|
|
}
|
|
|
|
// take care of tab labels
|
|
this._cleanup();
|
|
return this;
|
|
},
|
|
|
|
url: function (index, url) {
|
|
this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
|
|
return this;
|
|
},
|
|
|
|
length: function () {
|
|
return this.anchors.length;
|
|
},
|
|
});
|
|
|
|
$.extend($.ui.tabs, {
|
|
version: '1.8.22',
|
|
});
|
|
|
|
/*
|
|
* Tabs Extensions
|
|
*/
|
|
|
|
/*
|
|
* Rotate
|
|
*/
|
|
$.extend($.ui.tabs.prototype, {
|
|
rotation: null,
|
|
rotate: function (ms, continuing) {
|
|
var self = this,
|
|
o = this.options;
|
|
|
|
var rotate =
|
|
self._rotate ||
|
|
(self._rotate = function (e) {
|
|
clearTimeout(self.rotation);
|
|
self.rotation = setTimeout(function () {
|
|
var t = o.selected;
|
|
self.select(++t < self.anchors.length ? t : 0);
|
|
}, ms);
|
|
|
|
if (e) {
|
|
e.stopPropagation();
|
|
}
|
|
});
|
|
|
|
var stop =
|
|
self._unrotate ||
|
|
(self._unrotate = !continuing
|
|
? function (e) {
|
|
if (e.clientX) {
|
|
// in case of a true click
|
|
self.rotate(null);
|
|
}
|
|
}
|
|
: function (e) {
|
|
rotate();
|
|
});
|
|
|
|
// start rotation
|
|
if (ms) {
|
|
this.element.bind('tabsshow', rotate);
|
|
this.anchors.bind(o.event + '.tabs', stop);
|
|
rotate();
|
|
// stop rotation
|
|
} else {
|
|
clearTimeout(self.rotation);
|
|
this.element.off('tabsshow', rotate);
|
|
this.anchors.off(o.event + '.tabs', stop);
|
|
delete this._rotate;
|
|
delete this._unrotate;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
});
|
|
})(jQuery); |