mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-12 06:52:25 +00:00
+ Refactored zoom code into TabItem (was in TabItems and Page)
+ The "zoom prep", where the div is resized behind the scenes, is now much more robust; items can be rearranged while in this state (in response to new tabs opening, for instance), and everything still works out. + Group._activeTab is now a TabItem rather than a DOM element + Most of the old "mod" routine is now in the TabItem constructor; "mod" no longer exists
This commit is contained in:
parent
16af125c6e
commit
7ceb6f598e
@ -71,6 +71,9 @@ window.Group = function(listOfEls, options) {
|
||||
this.expanded = null;
|
||||
this.locked = (options.locked ? Utils.copy(options.locked) : {});
|
||||
this.topChild = null;
|
||||
|
||||
// Variable: _activeTab
|
||||
// The <TabItem> for the group's active tab.
|
||||
this._activeTab = null;
|
||||
|
||||
if(isPoint(options.userSize))
|
||||
@ -288,19 +291,16 @@ window.Group.prototype = iQ.extend(new Item(), new Subscribable(), {
|
||||
|
||||
// -----------
|
||||
// Function: setActiveTab
|
||||
// Sets the active tab (for keyboard selection, etc)
|
||||
// TODO: This currently accepts only the DOM element of a tab.
|
||||
// It should also take a TabItem...
|
||||
// Sets the active <TabItem> for this group
|
||||
setActiveTab: function(tab){
|
||||
Utils.assert('tab must be a TabItem', tab && tab.isATabItem);
|
||||
this._activeTab = tab;
|
||||
},
|
||||
|
||||
// -----------
|
||||
// Function: getActiveTab
|
||||
// Gets the active tab (for keyboard selection, etc)
|
||||
// TODO: This currently returns a DOM element of the selected tab.
|
||||
// It should probably actually be a TabItem...
|
||||
getActiveTab: function(tab){
|
||||
// Gets the active <TabItem> for this group
|
||||
getActiveTab: function(){
|
||||
return this._activeTab;
|
||||
},
|
||||
|
||||
@ -1053,10 +1053,10 @@ window.Group.prototype = iQ.extend(new Item(), new Subscribable(), {
|
||||
// Don't zoom in to the last tab for the new tab group.
|
||||
if( self.isNewTabsGroup() ) return;
|
||||
var activeTab = self.getActiveTab();
|
||||
if( activeTab ) TabItems.zoomTo(activeTab)
|
||||
// TODO: This should also accept TabItems
|
||||
if( activeTab )
|
||||
activeTab.zoomIn();
|
||||
else if(self.getChild(0))
|
||||
TabItems.zoomTo(self.getChild(0).tab.mirror.el);
|
||||
self.getChild(0).zoomIn();
|
||||
|
||||
self._mouseDownLocation = null;
|
||||
});
|
||||
|
@ -10,7 +10,51 @@ window.TabItem = function(container, tab) {
|
||||
|
||||
this.defaultSize = new Point(TabItems.tabWidth, TabItems.tabHeight);
|
||||
this.locked = {};
|
||||
this.isATabItem = true;
|
||||
this._zoomPrep = false;
|
||||
this.sizeExtra = new Point();
|
||||
|
||||
// ___ setup div
|
||||
var $div = iQ(container);
|
||||
var self = this;
|
||||
|
||||
$div.data('tabItem', this);
|
||||
$div.data('isDragging', false);
|
||||
$div.draggable(window.Groups.dragOptions);
|
||||
$div.droppable(window.Groups.dropOptions);
|
||||
|
||||
$div.mousedown(function(e) {
|
||||
if(!Utils.isRightClick(e))
|
||||
self.lastMouseDownTarget = e.target;
|
||||
});
|
||||
|
||||
$div.mouseup(function(e) {
|
||||
var same = (e.target == self.lastMouseDownTarget);
|
||||
self.lastMouseDownTarget = null;
|
||||
if(!same)
|
||||
return;
|
||||
|
||||
if(iQ(e.target).hasClass("close"))
|
||||
tab.close();
|
||||
else {
|
||||
if(!iQ(this).data('isDragging'))
|
||||
self.zoomIn();
|
||||
/*
|
||||
else
|
||||
tab.raw.pos = iQ(this).position(); // TODO: is this necessary?
|
||||
*/
|
||||
}
|
||||
});
|
||||
|
||||
iQ("<div>")
|
||||
.addClass('close')
|
||||
.appendTo($div);
|
||||
|
||||
iQ("<div>")
|
||||
.addClass('expander')
|
||||
.appendTo($div);
|
||||
|
||||
// ___ additional setup
|
||||
this._init(container);
|
||||
|
||||
this.reconnected = false;
|
||||
@ -66,13 +110,13 @@ window.TabItem.prototype = iQ.extend(new Item(), {
|
||||
_getSizeExtra: function() {
|
||||
var $container = iQ(this.container);
|
||||
|
||||
var widthExtra = parseInt($container.css('padding-left'))
|
||||
this.sizeExtra.x = parseInt($container.css('padding-left'))
|
||||
+ parseInt($container.css('padding-right'));
|
||||
|
||||
var heightExtra = parseInt($container.css('padding-top'))
|
||||
this.sizeExtra.y = parseInt($container.css('padding-top'))
|
||||
+ parseInt($container.css('padding-bottom'));
|
||||
|
||||
return new Point(widthExtra, heightExtra);
|
||||
return new Point(this.sizeExtra);
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -97,84 +141,92 @@ window.TabItem.prototype = iQ.extend(new Item(), {
|
||||
},
|
||||
|
||||
// ----------
|
||||
setBounds: function(rect, immediately) {
|
||||
setBounds: function(rect, immediately, options) {
|
||||
if(!isRect(rect)) {
|
||||
Utils.trace('TabItem.setBounds: rect is not a real rectangle!', rect);
|
||||
return;
|
||||
}
|
||||
|
||||
var $container = iQ(this.container);
|
||||
var $title = iQ('.tab-title', $container);
|
||||
var $thumb = iQ('.thumb', $container);
|
||||
var $close = iQ('.close', $container);
|
||||
var extra = this._getSizeExtra();
|
||||
var css = {};
|
||||
if(!options)
|
||||
options = {};
|
||||
|
||||
const minFontSize = 8;
|
||||
const maxFontSize = 15;
|
||||
|
||||
if(rect.left != this.bounds.left)
|
||||
css.left = rect.left;
|
||||
if(this._zoomPrep)
|
||||
this.bounds.copy(rect);
|
||||
else {
|
||||
var $container = iQ(this.container);
|
||||
var $title = iQ('.tab-title', $container);
|
||||
var $thumb = iQ('.thumb', $container);
|
||||
var $close = iQ('.close', $container);
|
||||
var extra = this._getSizeExtra();
|
||||
var css = {};
|
||||
|
||||
if(rect.top != this.bounds.top)
|
||||
css.top = rect.top;
|
||||
|
||||
if(rect.width != this.bounds.width) {
|
||||
css.width = rect.width - extra.x;
|
||||
var scale = css.width / TabItems.tabWidth;
|
||||
|
||||
// The ease function ".5+.5*Math.tanh(2*x-2)" is a pretty
|
||||
// little graph. It goes from near 0 at x=0 to near 1 at x=2
|
||||
// smoothly and beautifully.
|
||||
css.fontSize = minFontSize + (maxFontSize-minFontSize)*(.5+.5*Math.tanh(2*scale-2))
|
||||
}
|
||||
|
||||
if(rect.height != this.bounds.height) {
|
||||
css.height = rect.height - extra.y;
|
||||
}
|
||||
|
||||
if(iQ.isEmptyObject(css))
|
||||
return;
|
||||
|
||||
this.bounds.copy(rect);
|
||||
|
||||
// If this is a brand new tab don't animate it in from
|
||||
// a random location (i.e., from [0,0]). Instead, just
|
||||
// have it appear where it should be.
|
||||
if(immediately || (!this._hasBeenDrawn) ) {
|
||||
/* $container.stop(true, true); */
|
||||
$container.css(css);
|
||||
} else {
|
||||
TabMirror.pausePainting();
|
||||
$container.animate(css, {
|
||||
duration: 200,
|
||||
easing: 'tabcandyBounce',
|
||||
complete: function() {
|
||||
TabMirror.resumePainting();
|
||||
}
|
||||
});
|
||||
/* }).dequeue(); */
|
||||
}
|
||||
|
||||
if(css.fontSize && !this.inStack()) {
|
||||
if(css.fontSize < minFontSize )
|
||||
$title.fadeOut();//.dequeue();
|
||||
else
|
||||
$title.fadeIn();//.dequeue();
|
||||
}
|
||||
|
||||
if(css.width) {
|
||||
if(css.width < 30) {
|
||||
$thumb.fadeOut();
|
||||
$close.fadeOut();
|
||||
} else {
|
||||
$thumb.fadeIn();
|
||||
$close.fadeIn();
|
||||
const minFontSize = 8;
|
||||
const maxFontSize = 15;
|
||||
|
||||
if(rect.left != this.bounds.left)
|
||||
css.left = rect.left;
|
||||
|
||||
if(rect.top != this.bounds.top)
|
||||
css.top = rect.top;
|
||||
|
||||
if(rect.width != this.bounds.width) {
|
||||
css.width = rect.width - extra.x;
|
||||
var scale = css.width / TabItems.tabWidth;
|
||||
|
||||
// The ease function ".5+.5*Math.tanh(2*x-2)" is a pretty
|
||||
// little graph. It goes from near 0 at x=0 to near 1 at x=2
|
||||
// smoothly and beautifully.
|
||||
css.fontSize = minFontSize + (maxFontSize-minFontSize)*(.5+.5*Math.tanh(2*scale-2))
|
||||
}
|
||||
}
|
||||
|
||||
if(rect.height != this.bounds.height) {
|
||||
css.height = rect.height - extra.y;
|
||||
}
|
||||
|
||||
if(iQ.isEmptyObject(css) && !options.force)
|
||||
return;
|
||||
|
||||
this.bounds.copy(rect);
|
||||
|
||||
// If this is a brand new tab don't animate it in from
|
||||
// a random location (i.e., from [0,0]). Instead, just
|
||||
// have it appear where it should be.
|
||||
if(immediately || (!this._hasBeenDrawn) ) {
|
||||
/* $container.stop(true, true); */
|
||||
$container.css(css);
|
||||
} else {
|
||||
TabMirror.pausePainting();
|
||||
$container.animate(css, {
|
||||
duration: 200,
|
||||
easing: 'tabcandyBounce',
|
||||
complete: function() {
|
||||
TabMirror.resumePainting();
|
||||
}
|
||||
});
|
||||
/* }).dequeue(); */
|
||||
}
|
||||
|
||||
if(css.fontSize && !this.inStack()) {
|
||||
if(css.fontSize < minFontSize )
|
||||
$title.fadeOut();//.dequeue();
|
||||
else
|
||||
$title.fadeIn();//.dequeue();
|
||||
}
|
||||
|
||||
if(css.width) {
|
||||
if(css.width < 30) {
|
||||
$thumb.fadeOut();
|
||||
$close.fadeOut();
|
||||
} else {
|
||||
$thumb.fadeIn();
|
||||
$close.fadeIn();
|
||||
}
|
||||
}
|
||||
|
||||
this._hasBeenDrawn = true;
|
||||
}
|
||||
|
||||
this._updateDebugBounds();
|
||||
this._hasBeenDrawn = true;
|
||||
|
||||
if(!isRect(this.bounds))
|
||||
Utils.trace('TabItem.setBounds: this.bounds is not a real rectangle!', this.bounds);
|
||||
@ -257,10 +309,159 @@ window.TabItem.prototype = iQ.extend(new Item(), {
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: zoom
|
||||
// Zooms into this tab thereby allowing you to interact with it.
|
||||
zoom: function(){
|
||||
TabItems.zoomTo(this.container);
|
||||
// Function: zoomIn
|
||||
// Allows you to select the tab and zoom in on it, thereby bringing you
|
||||
// to the tab in Firefox to interact with.
|
||||
zoomIn: function() {
|
||||
var self = this;
|
||||
var $tabEl = iQ(this.container);
|
||||
var childHitResult = { shouldZoom: true };
|
||||
if(this.parent)
|
||||
childHitResult = this.parent.childHit(this);
|
||||
|
||||
if(childHitResult.shouldZoom) {
|
||||
// Zoom in!
|
||||
var orig = {
|
||||
width: $tabEl.width(),
|
||||
height: $tabEl.height(),
|
||||
pos: $tabEl.position()
|
||||
}
|
||||
|
||||
var scale = window.innerWidth/orig.width;
|
||||
|
||||
var tab = this.tab;
|
||||
var mirror = tab.mirror;
|
||||
|
||||
function onZoomDone(){
|
||||
UI.tabBar.show(false);
|
||||
TabMirror.resumePainting();
|
||||
tab.focus();
|
||||
$tabEl
|
||||
.css({
|
||||
top: orig.pos.top,
|
||||
left: orig.pos.left,
|
||||
width: orig.width,
|
||||
height:orig.height,
|
||||
})
|
||||
.removeClass("front");
|
||||
Navbar.show();
|
||||
|
||||
// If the tab is in a group set then set the active
|
||||
// group to the tab's parent.
|
||||
if( self.parent ){
|
||||
var gID = self.parent.id;
|
||||
var group = Groups.group(gID);
|
||||
Groups.setActiveGroup( group );
|
||||
group.setActiveTab( self );
|
||||
}
|
||||
else
|
||||
Groups.setActiveGroup( null );
|
||||
|
||||
if(childHitResult.callback)
|
||||
childHitResult.callback();
|
||||
}
|
||||
|
||||
// The scaleCheat is a clever way to speed up the zoom-in code.
|
||||
// Because image scaling is slowest on big images, we cheat and stop the image
|
||||
// at scaled-down size and placed accordingly. Because the animation is fast, you can't
|
||||
// see the difference but it feels a lot zippier. The only trick is choosing the
|
||||
// right animation function so that you don't see a change in percieved
|
||||
// animation speed.
|
||||
var scaleCheat = 1.7;
|
||||
TabMirror.pausePainting();
|
||||
$tabEl
|
||||
.addClass("front")
|
||||
.animate({
|
||||
top: orig.pos.top * (1-1/scaleCheat),
|
||||
left: orig.pos.left * (1-1/scaleCheat),
|
||||
width: orig.width*scale/scaleCheat,
|
||||
height: orig.height*scale/scaleCheat
|
||||
}, {
|
||||
duration: 230,
|
||||
easing: 'fast',
|
||||
complete: onZoomDone
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: zoomOut
|
||||
// Handles the zoom down animation after returning to TabCandy.
|
||||
// It is expected that this routine will be called from the chrome thread
|
||||
// (in response to Tabs.onFocus()).
|
||||
//
|
||||
// Parameters:
|
||||
// complete - a function to call after the zoom down animation
|
||||
zoomOut: function(complete) {
|
||||
var $tab = iQ(this.container);
|
||||
|
||||
var box = this.getBounds();
|
||||
box.width -= this.sizeExtra.x;
|
||||
box.height -= this.sizeExtra.y;
|
||||
|
||||
TabMirror.pausePainting();
|
||||
|
||||
var self = this;
|
||||
$tab.animate({
|
||||
left: box.left,
|
||||
top: box.top,
|
||||
width: box.width,
|
||||
height: box.height
|
||||
}, {
|
||||
duration: 300,
|
||||
easing: 'fast',
|
||||
complete: function() { // note that this will happen on the DOM thread
|
||||
$tab.removeClass('front');
|
||||
|
||||
TabMirror.resumePainting();
|
||||
|
||||
self._zoomPrep = false;
|
||||
self.setBounds(self.getBounds(), true, {force: true});
|
||||
|
||||
if(iQ.isFunction(complete))
|
||||
complete();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setZoomPrep
|
||||
// Either go into or return from (depending on <value>) "zoom prep" mode,
|
||||
// where the tab fills a large portion of the screen in anticipation of
|
||||
// the zoom out animation.
|
||||
setZoomPrep: function(value) {
|
||||
var $div = iQ(this.container);
|
||||
var data;
|
||||
|
||||
if(value) {
|
||||
this._zoomPrep = true;
|
||||
var box = this.getBounds();
|
||||
|
||||
// The divide by two part here is a clever way to speed up the zoom-out code.
|
||||
// Because image scaling is slowest on big images, we cheat and start the image
|
||||
// at half-size and placed accordingly. Because the animation is fast, you can't
|
||||
// see the difference but it feels a lot zippier. The only trick is choosing the
|
||||
// right animation function so that you don't see a change in percieved
|
||||
// animation speed from frame #1 (the tab) to frame #2 (the half-size image) to
|
||||
// frame #3 (the first frame of real animation). Choosing an animation that starts
|
||||
// fast is key.
|
||||
var scaleCheat = 2;
|
||||
$div
|
||||
.addClass('front')
|
||||
.css({
|
||||
left: box.left * (1-1/scaleCheat),
|
||||
top: box.top * (1-1/scaleCheat),
|
||||
width: window.innerWidth/scaleCheat,
|
||||
height: box.height * (window.innerWidth / box.width)/scaleCheat
|
||||
});
|
||||
} else {
|
||||
this._zoomPrep = false;
|
||||
$div.removeClass('front')
|
||||
|
||||
var box = this.getBounds();
|
||||
this.reloadBounds();
|
||||
this.setBounds(box, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -278,62 +479,23 @@ window.TabItems = {
|
||||
this.items = [];
|
||||
|
||||
var self = this;
|
||||
|
||||
function mod(mirror) {
|
||||
window.TabMirror.customize(function(mirror) {
|
||||
var $div = iQ(mirror.el);
|
||||
var tab = mirror.tab;
|
||||
|
||||
if(window.Groups) {
|
||||
$div.data('isDragging', false);
|
||||
$div.draggable(window.Groups.dragOptions);
|
||||
$div.droppable(window.Groups.dropOptions);
|
||||
}
|
||||
|
||||
$div.mousedown(function(e) {
|
||||
if(!Utils.isRightClick(e))
|
||||
self.lastMouseDownTarget = e.target;
|
||||
});
|
||||
|
||||
$div.mouseup(function(e) {
|
||||
var same = (e.target == self.lastMouseDownTarget);
|
||||
self.lastMouseDownTarget = null;
|
||||
if(!same)
|
||||
return;
|
||||
|
||||
if(iQ(e.target).hasClass("close"))
|
||||
tab.close();
|
||||
else {
|
||||
if(!iQ(this).data('isDragging'))
|
||||
self.zoomTo(this);
|
||||
else
|
||||
tab.raw.pos = iQ(this).position(); // TODO: is this necessary?
|
||||
}
|
||||
});
|
||||
|
||||
iQ("<div>")
|
||||
.addClass('close')
|
||||
.appendTo($div);
|
||||
|
||||
iQ("<div>")
|
||||
.addClass('expander')
|
||||
.appendTo($div);
|
||||
|
||||
|
||||
if(tab == Utils.homeTab)
|
||||
$div.hide();
|
||||
else {
|
||||
var item = new TabItem(mirror.el, tab);
|
||||
$div.data('tabItem', item);
|
||||
|
||||
item.addOnClose(self, function() {
|
||||
Items.unsquish(null, item);
|
||||
});
|
||||
|
||||
if(!TabItems.reconnect(item))
|
||||
if(!self.reconnect(item))
|
||||
Groups.newTab(item);
|
||||
}
|
||||
}
|
||||
|
||||
window.TabMirror.customize(mod);
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -349,94 +511,6 @@ window.TabItems = {
|
||||
this.items.splice(index, 1);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: zoomTo(container)
|
||||
// Given the containing element of a tab, allows you to
|
||||
// select that tab and zoom in on it, thereby bringing you
|
||||
// to the tab in Firefox to interact with.
|
||||
//
|
||||
zoomTo: function(tabEl){
|
||||
var self = this;
|
||||
var $tabEl = iQ(tabEl);
|
||||
var item = this.getItemByTabElement(tabEl);
|
||||
var childHitResult = { shouldZoom: true };
|
||||
if(item.parent)
|
||||
childHitResult = item.parent.childHit(item);
|
||||
|
||||
if(childHitResult.shouldZoom) {
|
||||
// Zoom in!
|
||||
var orig = {
|
||||
width: $tabEl.width(),
|
||||
height: $tabEl.height(),
|
||||
pos: $tabEl.position()
|
||||
}
|
||||
|
||||
var scale = window.innerWidth/orig.width;
|
||||
|
||||
var tab = Tabs.tab(tabEl);
|
||||
var mirror = tab.mirror;
|
||||
|
||||
var overflow = iQ("body").css("overflow");
|
||||
iQ("body").css("overflow", "hidden");
|
||||
|
||||
function onZoomDone(){
|
||||
try {
|
||||
UI.tabBar.show(false);
|
||||
TabMirror.resumePainting();
|
||||
tab.focus();
|
||||
$tabEl
|
||||
.css({
|
||||
top: orig.pos.top,
|
||||
left: orig.pos.left,
|
||||
width: orig.width,
|
||||
height:orig.height,
|
||||
})
|
||||
.removeClass("front");
|
||||
Navbar.show();
|
||||
|
||||
// If the tab is in a group set then set the active
|
||||
// group to the tab's parent.
|
||||
if( item.parent ){
|
||||
var gID = item.parent.id;
|
||||
var group = Groups.group(gID);
|
||||
Groups.setActiveGroup( group );
|
||||
group.setActiveTab( tabEl );
|
||||
}
|
||||
else
|
||||
Groups.setActiveGroup( null );
|
||||
|
||||
iQ("body").css("overflow", overflow);
|
||||
|
||||
if(childHitResult.callback)
|
||||
childHitResult.callback();
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
// The scaleCheat is a clever way to speed up the zoom-in code.
|
||||
// Because image scaling is slowest on big images, we cheat and stop the image
|
||||
// at scaled-down size and placed accordingly. Because the animation is fast, you can't
|
||||
// see the difference but it feels a lot zippier. The only trick is choosing the
|
||||
// right animation function so that you don't see a change in percieved
|
||||
// animation speed.
|
||||
var scaleCheat = 1.7;
|
||||
TabMirror.pausePainting();
|
||||
iQ(tabEl)
|
||||
.addClass("front")
|
||||
.animate({
|
||||
top: orig.pos.top * (1-1/scaleCheat),
|
||||
left: orig.pos.left * (1-1/scaleCheat),
|
||||
width: orig.width*scale/scaleCheat,
|
||||
height: orig.height*scale/scaleCheat
|
||||
}, {
|
||||
duration: 230,
|
||||
easing: 'fast',
|
||||
complete: onZoomDone
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
getItems: function() {
|
||||
return Utils.copy(this.items);
|
||||
@ -524,4 +598,3 @@ window.TabItems = {
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -229,7 +229,7 @@ window.Page = {
|
||||
break;
|
||||
case 49: // Command-1
|
||||
case 69: // Command-E
|
||||
if( Keys.meta ) if( self.getActiveTab() ) self.getActiveTab().zoom();
|
||||
if( Keys.meta ) if( self.getActiveTab() ) self.getActiveTab().zoomIn();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ window.Page = {
|
||||
}
|
||||
|
||||
if((e.which == 27 || e.which == 13) && iQ(":focus").length == 0 )
|
||||
if( self.getActiveTab() ) self.getActiveTab().zoom();
|
||||
if( self.getActiveTab() ) self.getActiveTab().zoomIn();
|
||||
|
||||
|
||||
|
||||
@ -256,8 +256,10 @@ window.Page = {
|
||||
// ----------
|
||||
init: function() {
|
||||
var self = this;
|
||||
/* Ian suspects we don't need these lines
|
||||
Utils.homeTab.raw.maxWidth = 60;
|
||||
Utils.homeTab.raw.minWidth = 60;
|
||||
*/
|
||||
|
||||
// When you click on the background/empty part of TabCandy
|
||||
// we create a new group.
|
||||
@ -295,97 +297,52 @@ window.Page = {
|
||||
if( focusTab.contentWindow == window ){
|
||||
UI.focused = true;
|
||||
Page.hideChrome();
|
||||
if(currentTab != null && currentTab.mirror != null) {
|
||||
|
||||
var item = null;
|
||||
if(currentTab && currentTab.mirror)
|
||||
item = TabItems.getItemByTabElement(currentTab.mirror.el);
|
||||
|
||||
if(item) {
|
||||
// If there was a previous currentTab we want to animate
|
||||
// its mirror for the zoom out.
|
||||
// Note that we start the animation on the chrome thread.
|
||||
|
||||
// Zoom out!
|
||||
var mirror = currentTab.mirror;
|
||||
var $tab = iQ(mirror.el);
|
||||
var data = $tab.data('zoomSave');
|
||||
var item = TabItems.getItemByTabElement(mirror.el);
|
||||
|
||||
TabMirror.pausePainting();
|
||||
|
||||
$tab.animate({
|
||||
left: data.pos.left,
|
||||
top: data.pos.top,
|
||||
width: data.w,
|
||||
height: data.h
|
||||
}, {
|
||||
duration: 300,
|
||||
easing: 'cubic-bezier',
|
||||
complete: function() { // note that this will happen on the DOM thread
|
||||
$tab.removeClass('front');
|
||||
|
||||
self.setActiveTab(item);
|
||||
var activeGroup = Groups.getActiveGroup();
|
||||
if( activeGroup )
|
||||
activeGroup.reorderBasedOnTabOrder(item);
|
||||
|
||||
window.Groups.setActiveGroup(null);
|
||||
TabMirror.resumePainting();
|
||||
UI.resize(true);
|
||||
}
|
||||
item.zoomOut(function() {
|
||||
self.setActiveTab(item);
|
||||
var activeGroup = Groups.getActiveGroup();
|
||||
if( activeGroup )
|
||||
activeGroup.reorderBasedOnTabOrder(item);
|
||||
|
||||
window.Groups.setActiveGroup(null);
|
||||
UI.resize(true);
|
||||
});
|
||||
}
|
||||
} else { // switched to another tab
|
||||
iQ.timeout(function() { // Marshal event from chrome thread to DOM thread
|
||||
UI.focused = false;
|
||||
Page.showChrome();
|
||||
var item = TabItems.getItemByTabElement(focusTab.mirror.el);
|
||||
if(item)
|
||||
Groups.setActiveGroup(item.parent);
|
||||
|
||||
var newItem = null;
|
||||
if(focusTab && focusTab.mirror)
|
||||
newItem = TabItems.getItemByTabElement(focusTab.mirror.el);
|
||||
|
||||
if(newItem)
|
||||
Groups.setActiveGroup(newItem.parent);
|
||||
|
||||
UI.tabBar.show();
|
||||
|
||||
// ___ prepare for when we return to TabCandy
|
||||
var oldItem = TabItems.getItemByTabElement(currentTab.mirror.el);
|
||||
if(item != oldItem) {
|
||||
var data;
|
||||
if(oldItem) {
|
||||
var $oldTab = iQ(oldItem.container);
|
||||
data = $oldTab.data('zoomSave');
|
||||
$oldTab
|
||||
.removeClass('front')
|
||||
.css({
|
||||
left: data.pos.left,
|
||||
top: data.pos.top,
|
||||
width: data.w,
|
||||
height: data.h
|
||||
});
|
||||
}
|
||||
|
||||
if(item) {
|
||||
var $tab = iQ(item.container);
|
||||
var oldItem = null;
|
||||
if(currentTab && currentTab.mirror)
|
||||
oldItem = TabItems.getItemByTabElement(currentTab.mirror.el);
|
||||
|
||||
if(newItem != oldItem) {
|
||||
if(oldItem)
|
||||
oldItem.setZoomPrep(false);
|
||||
|
||||
data = {
|
||||
pos: $tab.position(),
|
||||
w: $tab.width(),
|
||||
h: $tab.height()
|
||||
};
|
||||
|
||||
$tab.data('zoomSave', data);
|
||||
|
||||
// The divide by two part here is a clever way to speed up the zoom-out code.
|
||||
// Because image scaling is slowest on big images, we cheat and start the image
|
||||
// at half-size and placed accordingly. Because the animation is fast, you can't
|
||||
// see the difference but it feels a lot zippier. The only trick is choosing the
|
||||
// right animation function so that you don't see a change in percieved
|
||||
// animation speed from frame #1 (the tab) to frame #2 (the half-size image) to
|
||||
// frame #3 (the first frame of real animation). Choosing an animation that starts
|
||||
// fast is key.
|
||||
var scaleCheat = 2;
|
||||
$tab
|
||||
.addClass('front')
|
||||
.css({
|
||||
left: data.pos.left * (1-1/scaleCheat),
|
||||
top: data.pos.top * (1-1/scaleCheat),
|
||||
width: window.innerWidth/scaleCheat,
|
||||
height: data.h * (window.innerWidth / data.w)/scaleCheat
|
||||
});
|
||||
}
|
||||
if(newItem)
|
||||
newItem.setZoomPrep(true);
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
@ -468,7 +425,7 @@ window.Page = {
|
||||
// Function: setActiveTab
|
||||
// Sets the currently active tab. The idea of a focused tab is useful
|
||||
// for keyboard navigation and returning to the last zoomed-in tab.
|
||||
// Hiting return/esc brings you to the focused tab, and using the
|
||||
// Hitting return/esc brings you to the focused tab, and using the
|
||||
// arrow keys lets you navigate between open tabs.
|
||||
//
|
||||
// Parameters:
|
||||
|
@ -356,7 +356,7 @@ input.defaultName:hover{
|
||||
z-index: 999999 !important;
|
||||
-moz-border-radius: 0 !important;
|
||||
-moz-box-shadow: none !important;
|
||||
-moz-transform: none;
|
||||
-moz-transform: none !important;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user