diff --git a/css/admin.css b/css/admin.css
new file mode 100644
index 0000000000000000000000000000000000000000..b37ac91402748a7ab371624fb8917aab4f6390b9
--- /dev/null
+++ b/css/admin.css
@@ -0,0 +1,97 @@
+/* $Id$ */
+
+.views-tabset .views-tab fieldset {
+ margin-top: 0;
+}
+
+.views-tabset .views-tabs ul {
+ list-style-type: none !important;
+ list-style-image: none !important;
+ border: 1px solid black;
+ margin: 0;
+ padding: 0;
+}
+
+.views-tabset .views-tabs ul li {
+ list-style-type: none;
+ list-style-image: none;
+ background: none;
+ margin-left: 0;
+}
+
+.views-tabset .views-tabs ul li.active {
+ background: #ccc;
+ margin-left: 0;
+}
+
+
+.views-tabset .views-tabs {
+ float: left;
+ width: 120px;
+}
+
+.views-tabset .extra {
+ text-align: center;
+}
+
+.views-tabset .extra input {
+ margin-top: 0;
+}
+
+.views-tabset .views-tab-area {
+ border: 1px solid black;
+ margin-left: 119px; /* 120 -1 causes borders to overlap */
+ min-height: 300px;
+ _height: 300px; /* stupid IE hack */
+}
+
+.views-tab-area .tab-section {
+ width: 33%;
+ padding: 0;
+ margin: 0;
+ float: left;
+ min-height: 300px;
+ _height: 300px;
+}
+
+.views-tab-area .tab-section .inside {
+ margin: 0;
+ padding: 2px 5px;
+}
+
+.views-tab-area .tab-section .links {
+ float: right;
+}
+
+.views-tab-area .tab-section .links a {
+ font-size: small;
+}
+
+.views-tab-area .middle {
+ width: 34%;
+ background-color: #ccc;
+}
+
+.views-tab-area dl {
+ margin: 0;
+}
+
+.views-basic-info {
+ border: 1px solid black;
+ padding: 2px 5px;
+ background-color: #eee;
+}
+
+.views-ajax-pad {
+ border: 1px solid black;
+ margin-top: 10px;
+ min-height: 200px;
+ _height: 200px; /* stupid IE */
+}
+
+.views-ajax-pad .message {
+ margin-top: 75px;
+ text-align: center;
+}
+
+
diff --git a/css/tabs.css b/css/tabs.css
new file mode 100644
index 0000000000000000000000000000000000000000..5108f579741f75e2f2b2af4d968c0102b7139c28
--- /dev/null
+++ b/css/tabs.css
@@ -0,0 +1,3 @@
+.ui-tabs-hide {
+ display: none;
+}
diff --git a/js/base.js b/js/base.js
new file mode 100644
index 0000000000000000000000000000000000000000..8d8b1a28b0bd687207cc8f24a8d268f54e2962b9
--- /dev/null
+++ b/js/base.js
@@ -0,0 +1,11 @@
+Drupal.Views = {};
+
+/**
+ * jQuery UI tabs, Views integration component
+ */
+
+Drupal.behaviors.viewsTabs = function (context) {
+ $('.views-tabset:not(.views-processed)').addClass('views-processed').tabs({
+ selectedClass: 'active'
+ });
+}
diff --git a/js/tabs.js b/js/tabs.js
new file mode 100644
index 0000000000000000000000000000000000000000..62ce8a3ea58680d99a0db9a006f9b11f4bf3b242
--- /dev/null
+++ b/js/tabs.js
@@ -0,0 +1,433 @@
+/**
+ * jQuery UI Tabs (Tabs 3)
+ */
+(function($) {
+
+ // if the UI scope is not availalable, add it
+ $.ui = $.ui || {};
+
+ $.fn.tabs = function(initial, options) {
+ if (initial && initial.constructor == Object) { // shift arguments
+ options = initial;
+ initial = null;
+ }
+ options = options || {};
+
+ // first get initial tab from options
+ initial = initial && initial.constructor == Number && --initial || 0;
+
+ return this.each(function() {
+ new $.ui.tabs(this, $.extend(options, { initial: initial }));
+ });
+ };
+
+ // chainable tabs methods
+ $.each(['add', 'remove', 'enable', 'disable', 'click', 'load'], function(i, method) {
+ $.fn[method + 'Tab'] = function() {
+ var args = arguments;
+ return this.each(function() {
+ var instance = $.ui.tabs.instances[this.UI_TABS_UUID];
+ instance[method].apply(instance, args);
+ });
+ };
+ });
+ $.fn.selectedTab = function(returnElement) {
+ var selected;
+ if (returnElement) {
+
+ } else {
+
+ }
+ return selected;
+ };
+
+ $.ui.tabs = function(el, options) {
+
+ this.source = el;
+
+ this.options = $.extend({
+
+ // basic setup
+ initial: 0,
+ event: 'click',
+ disabled: [],
+ // TODO bookmarkable: $.ajaxHistory ? true : false,
+ unselected: false,
+ toggle: options.unselected ? true : false,
+
+ // Ajax
+ spinner: 'Loading…',
+ cache: false,
+ hashPrefix: 'tab-',
+
+ // animations
+ /*fxFade: null,
+ fxSlide: null,
+ fxShow: null,
+ fxHide: null,*/
+ fxSpeed: 'normal',
+ /*fxShowSpeed: null,
+ fxHideSpeed: null,*/
+
+ // callbacks
+ add: function() {},
+ remove: function() {},
+ enable: function() {},
+ disable: function() {},
+ click: function() {},
+ hide: function() {},
+ show: function() {},
+ load: function() {},
+
+ // CSS classes
+ navClass: 'ui-tabs-nav',
+ selectedClass: 'ui-tabs-selected',
+ disabledClass: 'ui-tabs-disabled',
+ containerClass: 'ui-tabs-container',
+ hideClass: 'ui-tabs-hide',
+ loadingClass: 'ui-tabs-loading'
+
+ }, options);
+
+ this.tabify(true);
+
+ // save instance for later
+ var uuid = 'instance-' + $.ui.tabs.prototype.count++;
+ $.ui.tabs.instances[uuid] = this;
+ this.source['UI_TABS_UUID'] = uuid;
+
+ };
+
+ // static
+ $.ui.tabs.instances = {};
+
+ $.extend($.ui.tabs.prototype, {
+ animating: false,
+ count: 0,
+ tabify: function(init) {
+
+ this.$tabs = $('a:first-child', this.source);
+ this.$containers = $([]);
+
+ var self = this, o = this.options;
+
+ this.$tabs.each(function(i, a) {
+ // inline tab
+ if (a.hash && a.hash.replace('#', '')) { // safari 2 reports '#' for an empty hash
+ self.$containers = self.$containers.add(a.hash);
+ }
+ // remote tab
+ else {
+ var id = a.title && a.title.replace(/\s/g, '_') || o.hashPrefix + (self.count + 1) + '-' + (i + 1), url = a.href;
+ a.href = '#' + id;
+ a.url = url;
+ self.$containers = self.$containers.add(
+ $('#' + id)[0] || $('
')
+ .insertAfter( self.$containers[i - 1] || self.source )
+ );
+ }
+ });
+
+ if (init) {
+
+ // Try to retrieve initial tab from fragment identifier in url if present,
+ // otherwise try to find selected class attribute on .
+ this.$tabs.each(function(i, a) {
+ if (location.hash) {
+ if (a.hash == location.hash) {
+ o.initial = i;
+ // prevent page scroll to fragment
+ //if (($.browser.msie || $.browser.opera) && !o.remote) {
+ if ($.browser.msie || $.browser.opera) {
+ var $toShow = $(location.hash), toShowId = $toShow.attr('id');
+ $toShow.attr('id', '');
+ setTimeout(function() {
+ $toShow.attr('id', toShowId); // restore id
+ }, 500);
+ }
+ scrollTo(0, 0);
+ return false; // break
+ }
+ } else if ( $(a).parents('li:eq(0)').is('li.' + o.selectedClass) ) {
+ o.initial = i;
+ return false; // break
+ }
+ });
+
+ // attach necessary classes for styling if not present
+ $(this.source).is('.' + o.navClass) || $(this.source).addClass(o.navClass);
+ this.$containers.each(function() {
+ var $this = $(this);
+ $this.is('.' + o.containerClass) || $this.addClass(o.containerClass);
+ });
+
+ // highlight tab accordingly
+ var $lis = $('li', this.source);
+ this.$containers.addClass(o.hideClass);
+ $lis.removeClass(o.selectedClass);
+ if (!o.unselected) {
+ this.$containers.slice(o.initial, o.initial + 1).show();
+ $lis.slice(o.initial, o.initial + 1).addClass(o.selectedClass);
+ }
+
+ // trigger load of initial tab is remote tab
+ if (this.$tabs[o.initial].url) {
+ this.load(o.initial + 1, this.$tabs[o.initial].url);
+ if (o.cache) {
+ this.$tabs[o.initial].url = null; // if loaded once do not load them again
+ }
+ }
+
+ // disabled tabs
+ for (var i = 0, position; position = o.disabled[i]; i++) {
+ this.disable(position);
+ }
+
+ }
+
+ // setup animations
+ var showAnim = {}, hideAnim = {}, showSpeed = o.fxShowSpeed || o.fxSpeed,
+ hideSpeed = o.fxHideSpeed || o.fxSpeed;
+ if (o.fxSlide || o.fxFade) {
+ if (o.fxSlide) {
+ showAnim['height'] = 'show';
+ hideAnim['height'] = 'hide';
+ }
+ if (o.fxFade) {
+ showAnim['opacity'] = 'show';
+ hideAnim['opacity'] = 'hide';
+ }
+ } else {
+ if (o.fxShow) {
+ showAnim = o.fxShow;
+ } else { // use some kind of animation to prevent browser scrolling to the tab
+ showAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox
+ showSpeed = 1; // as little as 1 is sufficient
+ }
+ if (o.fxHide) {
+ hideAnim = o.fxHide;
+ } else { // use some kind of animation to prevent browser scrolling to the tab
+ hideAnim['min-width'] = 0; // avoid opacity, causes flicker in Firefox
+ hideSpeed = 1; // as little as 1 is sufficient
+ }
+ }
+
+ // callbacks
+ var click = o.click, hide = o.hide, show = o.show;
+
+ // reset some styles to maintain print style sheets etc.
+ var resetCSS = { display: '', overflow: '', height: '' };
+ if (!$.browser.msie) { // not in IE to prevent ClearType font issue
+ resetCSS['opacity'] = '';
+ }
+
+ // hide a tab, animation prevents browser scrolling to fragment
+ function hideTab(clicked, $hide, $show) {
+ $hide.animate(hideAnim, hideSpeed, function() { //
+ $hide.addClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
+ hide(clicked, $show, $hide[0]);
+ if ($show) {
+ showTab(clicked, $hide, $show);
+ }
+ });
+ }
+
+ // show a tab, animation prevents browser scrolling to fragment
+ function showTab(clicked, $hide, $show) {
+ // show next tab
+ if (!(o.fxSlide || o.fxFade || o.fxShow)) {
+ $show.css('display', 'block'); // prevent occasionally occuring flicker in Firefox cause by gap between showing and hiding the tab containers
+ }
+ $show.animate(showAnim, showSpeed, function() {
+ $show.removeClass(o.hideClass).css(resetCSS); // maintain flexible height and accessibility in print etc.
+ if ($.browser.msie) {
+ $hide[0].style.filter = '';
+ $show[0].style.filter = '';
+ }
+ show(clicked, $show[0], $hide[0]);
+ self.animating = false;
+ });
+
+ }
+
+ // switch a tab
+ function switchTab(clicked, $hide, $show) {
+ /*if (o.bookmarkable && trueClick) { // add to history only if true click occured, not a triggered click
+ $.ajaxHistory.update(clicked.hash);
+ }*/
+ $(clicked).parents('li:eq(0)').addClass(o.selectedClass)
+ .siblings().removeClass(o.selectedClass);
+ hideTab(clicked, $hide, $show);
+ }
+
+ // tab click handler
+ function tabClick(e) {
+
+ //var trueClick = e.clientX; // add to history only if true click occured, not a triggered click
+ var $li = $(this).parents('li:eq(0)'), $hide = self.$containers.filter(':visible'), $show = $(this.hash);
+
+ // if tab may be closed
+ if (o.toggle && !$li.is('.' + o.disabledClass) && !self.animating) {
+ if ($li.is('.' + o.selectedClass)) {
+ $li.removeClass(o.selectedClass);
+ hideTab(this, $hide);
+ this.blur();
+ return false;
+ } else if (!$hide.length) {
+ $li.addClass(o.selectedClass);
+ showTab(this, $hide, $show);
+ this.blur();
+ return false;
+ }
+ }
+
+ // If tab is already selected or disabled, animation is still running or click callback
+ // returns false stop here.
+ // Check if click handler returns false last so that it is not executed for a disabled tab!
+ if ($li.is('.' + o.selectedClass + ', .' + o.disabledClass)
+ || self.animating || click(this, $show[0], $hide[0]) === false) {
+ this.blur();
+ return false;
+ }
+
+ self.animating = true;
+
+ // show new tab
+ if ($show.length) {
+
+ // prevent scrollbar scrolling to 0 and than back in IE7, happens only if bookmarking/history is enabled
+ /*if ($.browser.msie && o.bookmarkable) {
+ var showId = this.hash.replace('#', '');
+ $show.attr('id', '');
+ setTimeout(function() {
+ $show.attr('id', showId); // restore id
+ }, 0);
+ }*/
+
+ if (this.url) { // remote tab
+ var a = this;
+ self.load(self.$tabs.index(this) + 1, this.url, function() {
+ switchTab(a, $hide, $show);
+ });
+ if (o.cache) {
+ this.url = null; // if loaded once do not load them again
+ }
+ } else {
+ switchTab(this, $hide, $show);
+ }
+
+ // Set scrollbar to saved position - need to use timeout with 0 to prevent browser scroll to target of hash
+ /*var scrollX = window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft || 0;
+ var scrollY = window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop || 0;
+ setTimeout(function() {
+ scrollTo(scrollX, scrollY);
+ }, 0);*/
+
+ } else {
+ throw 'jQuery UI Tabs: Mismatching fragment identifier.';
+ }
+
+ this.blur(); // prevent IE from keeping other link focussed when using the back button
+
+ //return o.bookmarkable && !!trueClick; // convert trueClick == undefined to Boolean required in IE
+ return false;
+
+ }
+
+ // attach click event, avoid duplicates from former tabifying
+ this.$tabs.unbind(o.event, tabClick).bind(o.event, tabClick);
+
+ },
+ add: function(url, text, position) {
+ if (url && text) {
+ var o = this.options;
+ position = position || this.$tabs.length; // append by default
+ if (position >= this.$tabs.length) {
+ var method = 'insertAfter';
+ position = this.$tabs.length;
+ } else {
+ var method = 'insertBefore';
+ }
+ if (url.indexOf('#') == 0) { // ajax container is created by tabify automatically
+ var $container = $(url);
+ // try to find an existing element before creating a new one
+ ($container.length && $container || $(''))
+ [method](this.$containers[position - 1]);
+ }
+ $('' + text + '')
+ [method](this.$tabs.slice(position - 1, position).parents('li:eq(0)'));
+ this.tabify();
+ o.add(this.$tabs[position - 1], this.$containers[position - 1]); // callback
+ } else {
+ throw 'jQuery UI Tabs: Not enough arguments to add tab.';
+ }
+ },
+ remove: function(position) {
+ if (position && position.constructor == Number) {
+ this.$tabs.slice(position - 1, position).parents('li:eq(0)').remove();
+ this.$containers.slice(position - 1, position).remove();
+ this.tabify();
+ }
+ this.options.remove(); // callback
+ },
+ enable: function(position) {
+ var $li = this.$tabs.slice(position - 1, position).parents('li:eq(0)'), o = this.options;
+ $li.removeClass(o.disabledClass);
+ if ($.browser.safari) { // fix disappearing tab after enabling in Safari... TODO check Safari 3
+ $li.animate({ opacity: 1 }, 1, function() {
+ $li.css({ opacity: '' });
+ });
+ }
+ o.enable(this.$tabs[position - 1], this.$containers[position - 1]); // callback
+ },
+ disable: function(position) {
+ var $li = this.$tabs.slice(position - 1, position).parents('li:eq(0)'), o = this.options;
+ if ($.browser.safari) { // fix opacity of tab after disabling in Safari... TODO check Safari 3
+ $li.animate({ opacity: 0 }, 1, function() {
+ $li.css({ opacity: '' });
+ });
+ }
+ $li.addClass(this.options.disabledClass);
+ o.disable(this.$tabs[position - 1], this.$containers[position - 1]); // callback
+ },
+ click: function(position) {
+ this.$tabs.slice(position - 1, position).trigger('click');
+ },
+ load: function(position, url, callback) {
+ var self = this,
+ o = this.options,
+ $a = this.$tabs.slice(position - 1, position).addClass(o.loadingClass),
+ $span = $('span', $a),
+ text = $span.html();
+
+ // shift arguments
+ if (url && url.constructor == Function) {
+ callback = url;
+ }
+
+ // set new URL
+ if (url) {
+ $a[0].url = url;
+ }
+
+ // load
+ if (o.spinner) {
+ $span.html('' + o.spinner + '');
+ }
+ setTimeout(function() { // timeout is again required in IE, "wait" for id being restored
+ $($a[0].hash).load(url, function() {
+ if (o.spinner) {
+ $span.html(text);
+ }
+ $a.removeClass(o.loadingClass);
+ // This callback is needed because the switch has to take place after loading
+ // has completed.
+ if (callback && callback.constructor == Function) {
+ callback();
+ }
+ o.load(self.$tabs[position - 1], self.$containers[position - 1]); // callback
+ });
+ }, 0);
+ }
+ });
+})(jQuery);