javascripts/right-tabs-src.js in right-rails-0.4.4 vs javascripts/right-tabs-src.js in right-rails-0.5.0
- old
+ new
@@ -1,15 +1,15 @@
/**
* Unified tabs engine for RightJS (http://rightjs.org/ui/tabs)
*
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
if (!RightJS) throw "Gimme RightJS";
/**
* The basic tabs handling engine
*
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
var Tabs = new Class(Observer, {
extend: {
EVENTS: $w('show hide click load disable enable add remove move'),
@@ -149,11 +149,11 @@
});
/**
* A single tab handling object
*
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
Tabs.Tab = new Class({
extend: {
autoId: 0
},
@@ -259,11 +259,11 @@
});
/**
* The tab panels behavior logic
*
- * Copyright (C) Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
Tabs.Panel = new Class(Observer, {
initialize: function(element, tab) {
this.tab = tab;
@@ -272,57 +272,62 @@
},
// shows the panel
show: function() {
return this.resizing(function() {
- this.element.radioClass('right-tabs-panel-current');
+ this.tab.controller.tabs.each(function(tab) {
+ var element = tab.panel.element;
+ element[element == this.element ?
+ 'addClass' : 'removeClass']('right-tabs-panel-current');
+ }, this);
});
},
// updates the panel content
update: function(content) {
- return this.resizing(function() {
+ // don't use resize if it's some other hidden tab was loaded asynch
+ if (this.tab.current()) {
+ this.resizing(function() {
+ this.element.update(content||'');
+ });
+ } else {
this.element.update(content||'');
- });
+ }
+
+ return this;
},
// removes the pannel
remove: function() {
this.element.remove();
return this;
},
// locks the panel with a spinner locker
lock: function() {
- var locker = $E('div', {'class': 'right-tabs-panel-locker'});
- var spinner = $E('div', {'class': 'right-tabs-panel-locker-spinner'}).insertTo(locker);
- var dots = '1234'.split('').map(function(i) {
- return $E('div', {'class': i == 1 ? 'glow':null}).insertTo(spinner);
- });
-
- (function() {
- spinner.insert(dots.last(), 'top');
- dots.unshift(dots.pop());
- }).periodical(400);
-
- this.element.insert(locker, 'top');
+ this.element.insert(this.locker(), 'top');
},
// protected
resizing: function(callback) {
- if (Tabs.__working) return this.resizing.bind(this, callback).delay(20);
-
var controller = this.tab.controller;
+
+ if (controller.__working) return this.resizing.bind(this, callback).delay(100);
+
var options = controller.options;
var prev_panel = controller.element.first('.right-tabs-panel-current');
var this_panel = this.element;
var swapping = prev_panel != this_panel;
var loading = this.element.first('div.right-tabs-panel-locker');
+ // sometimes it looses the parent on remote tabs
+ if (this_panel.parentNode.hasClass('right-tabs-resizer')) this_panel.insertTo(prev_panel.parentNode);
+
if (options.resizeFx && self.Fx && prev_panel && (swapping || loading)) {
- Tabs.__working = true;
+ controller.__working = true;
+ var unlock = function() { controller.__working = false; };
// calculating the visual effects durations
var fx_name = (options.resizeFx == 'both' && loading) ? 'slide' : options.resizeFx;
var duration = options.resizeDuration; duration = Fx.Durations[duration] || duration;
var resize_duration = fx_name == 'fade' ? 0 : fx_name == 'slide' ? duration : duration / 2;
@@ -337,19 +342,21 @@
// applying the changes
callback.call(this);
// getting the new size
var new_panel_height = this_panel.offsetHeight;
+ var fx_wrapper = null;
if (fx_name != 'fade' && prev_panel_height != new_panel_height) {
// preserving the whole element size so it didn't jump when we are tossing the tabs around
controller.element.style.height = controller.element.offsetHeight + 'px';
// wrapping the element with an overflowed element to visualize the resize
- var fx_wrapper = $E('div', {'class': 'right-tabs-resizer'});
- var set_back = fx_wrapper.replace.bind(fx_wrapper, this_panel);
- fx_wrapper.style.height = prev_panel_height + 'px';
+ fx_wrapper = $E('div', {
+ 'class': 'right-tabs-resizer',
+ 'style': 'height: '+ prev_panel_height + 'px'
+ });
// in case of harmonica nicely hidding the previous panel
if (controller.isHarmonica && swapping) {
prev_panel.addClass('right-tabs-panel-current');
var hide_wrapper = $E('div', {'class': 'right-tabs-resizer'});
@@ -365,28 +372,68 @@
this_panel.wrap(fx_wrapper);
// getting back the auto-size so we could resize it
controller.element.style.height = 'auto';
- if (hide_wrapper) hide_wrapper.morph({height: '0px'}, {duration: resize_duration, onFinish: prev_back});
- fx_wrapper.morph({height: new_panel_height + 'px'}, {duration: resize_duration, onFinish: set_back });
} else {
// removing the resize duration out of the equasion
rezise_duration = 0;
duration = fade_duration;
}
- if (fx_name != 'slide')
- this_panel.morph.bind(this_panel, {opacity: 1}, {duration: fade_duration}).delay(resize_duration);
+ var counter = 0;
+ var set_back = function() {
+ if (fx_wrapper) {
+ if (fx_name == 'both' && !counter)
+ return counter ++;
+
+ fx_wrapper.replace(this_panel);
+ }
+
+ unlock();
+ };
- // removing the working marker
- (function() { Tabs.__working = false; }).bind(this).delay(duration);
+ if (hide_wrapper)
+ hide_wrapper.morph({height: '0px'},
+ {duration: resize_duration, onFinish: prev_back});
+
+ if (fx_wrapper)
+ fx_wrapper.morph({height: new_panel_height + 'px'},
+ {duration: resize_duration, onFinish: set_back});
+
+ if (fx_name != 'slide')
+ this_panel.morph.bind(this_panel, {opacity: 1},
+ {duration: fade_duration, onFinish: set_back}
+ ).delay(resize_duration);
+
+ if (!fx_wrapper && fx_name == 'slide')
+ set_back();
+
} else {
callback.call(this);
}
return this;
+ },
+
+ // builds the locker element
+ locker: function() {
+ if (!this._locker) {
+ var locker = $E('div', {'class': 'right-tabs-panel-locker'});
+ var spinner = $E('div', {'class': 'right-tabs-panel-locker-spinner'}).insertTo(locker);
+ var dots = '1234'.split('').map(function(i) {
+ return $E('div', {'class': i == 1 ? 'glow':null}).insertTo(spinner);
+ });
+
+ (function() {
+ spinner.insert(dots.last(), 'top');
+ dots.unshift(dots.pop());
+ }).periodical(400);
+
+ this._locker = locker;
+ }
+ return this._locker;
}
});
/**
@@ -395,11 +442,11 @@
* NOTE: different types of tabs have different scrolling behavior
* simple tabs just scroll the tabs line without actually picking
* any tab. But the carousel tabs scrolls to the next/previous
* tabs on the list.
*
- * Copyright (C) Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
Tabs.include((function() {
var old_init = Tabs.prototype.init;
return {
@@ -563,11 +610,11 @@
}})());
/**
* This module handles the current tab state saving/restoring processes
*
- * Copyright (C) Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
Tabs.include((function() {
var old_initialize = Tabs.prototype.initialize;
var get_cookie_indexes = function() {
@@ -647,11 +694,11 @@
}})());
/**
* This module handles the tabs cration and removing processes
*
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
Tabs.include({
/**
* Creates a new tab
*
@@ -728,19 +775,21 @@
});
/**
* This module contains the remote tabs loading logic
*
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
Tabs.Tab.include((function() {
var old_show = Tabs.Tab.prototype.show;
return {
// wrapping the show mehtod, to catch the remote requests
show: function() {
+ if (this.dogPiling(arguments)) return this;
+
var result = old_show.apply(this, arguments);
var url = this.link.href;
var options = this.controller.options;
// building the url
@@ -750,32 +799,54 @@
// if there is an actual url and no ongoing request or a cache, starting the request
if (url && !this.request && !(options.cache || this.cache)) {
this.panel.lock();
try { // basically that's for the development tests, so the IE browsers didn't get screwed on the test page
-
- this.request = Xhr.load(url, options.Xhr).onComplete(function(response) {
- this.panel.update(response.text);
+
+ this.request = new Xhr(url, Object.merge({method: 'get'}, options.Xhr))
+ .onComplete(function(response) {
+ if (this.controller.__working)
+ return arguments.callee.bind(this, response).delay(100);
+
+ this.panel.update(response.text);
- this.request = null; // removing the request marker so it could be rerun
- if (options.cache) this.cache = true;
+ this.request = null; // removing the request marker so it could be rerun
+ if (options.cache) this.cache = true;
- this.fire('load');
- }.bind(this));
+ this.fire('load');
+ }.bind(this)
+ ).send();
} catch(e) { if (!Browser.OLD) throw(e) }
}
return result;
+ },
+
+// protected
+
+ dogPiling: function(args) {
+ if (this.controller.__working) {
+ if (this.controller.__timeout)
+ this.controller.__timeout.cancel();
+
+ this.controller.__timeout = (function(args) {
+ this.show.apply(this, args);
+ }).bind(this, args).delay(100);
+
+ return true;
+ }
+
+ return this.controller.__timeout = null;
}
}})());
/**
* This module handles the slide-show loop feature for the Tabs
*
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
Tabs.include((function() {
var old_initialize = Tabs.prototype.initialize;
return {
@@ -850,10 +921,10 @@
}})());
/**
* The document level hooks for the tabs-egnine
*
- * Copyright (C) 2009 Nikolay V. Nemshilov aka St.
+ * Copyright (C) 2009-2010 Nikolay V. Nemshilov
*/
document.onReady(function() {
Tabs.rescan();
});
\ No newline at end of file