+ Fixed a bug making it so you couldn't close tabs that were just .mov

+ Commented out the _render routine in toolbar-button.js,  as it was throwing exceptions and didn't seem to work anyway
+ Added some asserts to Item and cleaned up its documentation
+ Made Utils.assert more robust
+ Made tabs prettier when stacked
+ Commented out js lint, which doesn't seem to work in this context
+ Fixed it so you can't resize locked groups
+ Made it so the "new tabs" group is no longer locked (for the time being at least)
+ Tabs no longer change order when you drag their groups around
+ The tray now goes away more beautifully
+ You now have to drag at least 100 pixels and at least 500 milliseconds before a tab is pulled out its tray
+ No longer reserving space at the bottom of the screen for the "new tabs" group
+ Tab titles now go away when stacked and come back when not (there was a problem with them coming back)
+ No longer explicitly positioning the "new tabs" group
This commit is contained in:
Ian Gilman 2010-04-30 17:24:03 -07:00
parent 8e2f4638c6
commit 89723d2a2c
8 changed files with 147 additions and 54 deletions

View File

@ -171,7 +171,9 @@ window.Group = function(listOfEls, options) {
// ___ Finish Up
this._addHandlers($container);
this.setResizable(true);
if(!this.locked)
this.setResizable(true);
Groups.register(this);
@ -314,9 +316,14 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
if(this.$debug)
this.$debug.css({zIndex: value + 1});
$.each(this._children, function(index, child) {
child.setZ(value + 1);
});
var count = this._children.length;
if(count) {
var zIndex = value + count + 1;
$.each(this._children, function(index, child) {
child.setZ(zIndex);
zIndex--;
});
}
},
// ----------
@ -336,7 +343,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
$.each(toClose, function(index, child) {
child.close();
});
} else
} else if(!this.locked)
this.close();
},
@ -484,6 +491,9 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
// ----------
arrange: function(options) {
if(this.expanded)
return;
var count = this._children.length;
if(!count)
return;
@ -649,7 +659,22 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
// ----------
collapse: function() {
if(this.expanded) {
this.expanded.$tray.remove();
var z = this.getZ();
var box = this.getBounds();
this.expanded.$tray
.css({
zIndex: z + 1
})
.animate({
width: box.width,
height: box.height,
top: box.top,
left: box.left,
opacity: 0
}, 350, "tabcandyBounce", function() {
$(this).remove();
});
this.expanded.$shield.remove();
this.expanded = null;
@ -657,7 +682,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
child.removeClass("stack-trayed");
});
this.arrange({z: this.getZ() + 1});
this.arrange({z: z + 2});
}
},
@ -669,8 +694,8 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
$(container).draggable({
scroll: false,
cancel: '.close, .name',
start: function(){
drag.info = new DragInfo(this);
start: function(e, ui){
drag.info = new DragInfo(this, e);
},
drag: function(e, ui){
drag.info.drag(e, ui);
@ -731,11 +756,13 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
});
// ##########
var DragInfo = function(element) {
var DragInfo = function(element, event) {
this.el = element;
this.$el = $(this.el);
this.item = Items.item(this.el);
this.parent = this.item.parent;
this.startPosition = new Point(event.clientX, event.clientY);
this.startTime = Utils.getMilliseconds();
this.$el.data('isDragging', true);
this.item.setZ(99999);
@ -743,7 +770,7 @@ var DragInfo = function(element) {
DragInfo.prototype = {
// ----------
drag: function(e, ui) {
drag: function(event, ui) {
if(this.item.isAGroup) {
var bb = this.item.getBounds();
bb.left = ui.position.left;
@ -753,9 +780,13 @@ DragInfo.prototype = {
this.item.reloadBounds();
if(this.parent && this.parent.expanded) {
this.item.locked = true;
this.parent.collapse();
this.item.locked = false;
var now = Utils.getMilliseconds();
var distance = this.startPosition.distance(new Point(event.clientX, event.clientY));
if(now - this.startTime > 500 && distance > 100) {
this.item.locked = true;
this.parent.collapse();
this.item.locked = false;
}
}
},
@ -791,9 +822,8 @@ window.Groups = {
dragOptions: {
scroll: false,
cancel: '.close',
refreshPositions: true,
start: function(e, ui) {
drag.info = new DragInfo(this);
drag.info = new DragInfo(this, e);
},
drag: function(e, ui) {
drag.info.drag(e, ui);
@ -884,12 +914,15 @@ window.Groups = {
if(data && data.groups) {
$.each(data.groups, function(index, group) {
new Group([], $.extend({}, group, {dontPush: true}));
new Group([], $.extend({}, group, {locked: false, dontPush: true}));
});
} else {
var box = this.getBoundsForNewTabGroup();
new Group([], {bounds: box, title: 'New Tabs', locked: true, dontPush: true});
}
var group = this.getNewTabGroup();
if(!group) {
var box = this.getBoundsForNewTabGroup();
new Group([], {bounds: box, title: 'New Tabs', dontPush: true});
}
},
// ----------
@ -1005,9 +1038,12 @@ window.Groups = {
// ----------
setActiveGroup: function(group) {
try{
this._activeGroup = group;
UI.tabBar.showOnlyTheseTabs( group._children );
}catch(e){Utils.log(e)}
this._activeGroup = group;
if(group)
UI.tabBar.showOnlyTheseTabs( group._children );
}catch(e){
Utils.log(e)
}
}
};

View File

@ -1,31 +1,19 @@
// Title: items.js (revision-a)
// ##########
// An Item is an object that adheres to an interface consisting of these methods:
// Class: Item
// Superclass for all visible objects (<TabItems> and <Group>s).
// If you subclass, in addition to the things Item provides, you need to also
// provide these methods:
// reloadBounds: function()
// getBounds: function(), inherited from Item
// setBounds: function(rect, immediately)
// setPosition: function(left, top, immediately), inherited from Item
// setSize: function(width, height, immediately), inherited from Item
// getZ: function(), inherited from Item
// setZ: function(value)
// close: function()
// addOnClose: function(referenceObject, callback)
// removeOnClose: function(referenceObject)
//
// In addition, it must have these properties:
// isAnItem, set to true (set by Item)
// ... and this property:
// defaultSize, a Point
// bounds, a Rect (set by Item in _init() via reloadBounds())
// debug (set by Item)
// $debug (set by Item in _init())
// container, a DOM element (set by Item in _init())
//
// Its container must also have a jQuery data named 'item' that points to the item.
// This is set by Item in _init().
// Class: Item
// Superclass for all visible objects (tabs and groups).
// Make sure to call _init() from your subclass's constructor.
window.Item = function() {
// Variable: isAnItem
// Always true for Items
@ -74,6 +62,15 @@ window.Item.prototype = {
// Parameters:
// container - the outermost DOM element that describes this item onscreen.
_init: function(container) {
Utils.assert('container must be a DOM element', Utils.isDOMElement(container));
Utils.assert('Subclass must provide reloadBounds', typeof(this.reloadBounds) == 'function');
Utils.assert('Subclass must provide setBounds', typeof(this.setBounds) == 'function');
Utils.assert('Subclass must provide setZ', typeof(this.setZ) == 'function');
Utils.assert('Subclass must provide close', typeof(this.close) == 'function');
Utils.assert('Subclass must provide addOnClose', typeof(this.addOnClose) == 'function');
Utils.assert('Subclass must provide removeOnClose', typeof(this.removeOnClose) == 'function');
Utils.assert('Subclass must provide defaultSize', this.defaultSize);
this.container = container;
if(this.debug) {
@ -87,6 +84,8 @@ window.Item.prototype = {
}
this.reloadBounds();
Utils.assert('reloadBounds must set up this.bounds', this.bounds);
$(this.container).data('item', this);
},
@ -436,7 +435,7 @@ window.Items = {
// Returns a <Rect> defining the area of the page <Item>s should stay within.
getPageBounds: function() {
var top = 20;
var bottom = TabItems.tabHeight + 10; // MAGIC NUMBER: giving room for the "new tabs" group
var bottom = 20;//TabItems.tabHeight + 10; // MAGIC NUMBER: giving room for the "new tabs" group
var width = Math.max(100, window.innerWidth);
var height = Math.max(100, window.innerHeight - (top + bottom));
return new Rect(0, top, width, height);

View File

@ -1,8 +1,8 @@
// ##########
window.TabItem = function(container, tab) {
this.defaultSize = new Point(TabItems.tabWidth, TabItems.tabHeight);
this._init(container);
this.tab = tab;
this.defaultSize = new Point(TabItems.tabWidth, TabItems.tabHeight);
this.setResizable(true);
};
@ -105,18 +105,13 @@ window.TabItem.prototype = $.extend(new Item(), {
}).dequeue();
}
if(css.fontSize) {
if(css.fontSize && !$container.hasClass("stacked")) {
if(css.fontSize < minFontSize )
$title.fadeOut().dequeue();
else
$title.fadeIn().dequeue();
}
if( $container.hasClass("stacked") ){
$title.hide();
}
if(css.width) {
if(css.width < 30) {
$thumb.fadeOut();

View File

@ -347,6 +347,9 @@ function UIClass(){
self.resize();
});
// ___ Dev Menu
/* this.addDevMenu(); */
// ___ Done
this.initialized = true;
};
@ -367,7 +370,7 @@ UIClass.prototype = {
// ----------
resize: function() {
Groups.repositionNewTabGroup();
/* Groups.repositionNewTabGroup(); */
var items = Items.getTopLevelItems();
var itemBounds = new Rect(this.pageBounds);
@ -423,6 +426,44 @@ UIClass.prototype = {
this.pageBounds = Items.getPageBounds();
},
// ----------
addDevMenu: function() {
var html = '<select style="position:absolute">'
+ '<option>*</option>';
/*
var names = Utils.getVisualizationNames();
var count = names.length;
var a;
for(a = 0; a < count; a++) {
var name = names[a];
html += '<option value="'
+ name
+ '"'
+ (name == myName ? ' selected="true"' : '')
+ '>'
+ name
+ '</option>';
}
html += '<option disabled="disabled">----------</option>';
html += '<option value="">Home</option>';
*/
html += '</select>';
$('body')
.append(html)
.change(function () {
/*
var name = $(this).val();
if(name)
location.href = '../' + name + '/index.html';
else
location.href = '../../index.html';
*/
});
},
// ----------
_addArrangements: function() {
this.grid = new ArrangeClass("Grid", function(value) {

View File

@ -38,7 +38,11 @@ TabCanvas.prototype = {
},
detach: function() {
this.tab.contentWindow.removeEventListener("MozAfterPaint", this.paintIt, false);
try {
this.tab.contentWindow.removeEventListener("MozAfterPaint", this.paintIt, false);
} catch(e) {
// ignore
}
},
paint: function(evt){

View File

@ -37,6 +37,13 @@ window.Point = function(a, y) {
}
window.Point.prototype = {
// ----------
distance: function(point) {
var ax = Math.abs(this.x - point.x);
var ay = Math.abs(this.y - point.y);
return Math.sqrt((ax * ax) + (ay * ay));
},
// ----------
plus: function(point) {
return new Point(this.x + point.x, this.y + point.y);
@ -326,7 +333,12 @@ var Utils = {
assert: function(label, condition) {
if(!condition) {
var text = 'tabcandy assert: ' + label;
var text;
if(typeof(label) == 'undefined')
text = 'badly formed assert';
else
text = 'tabcandy assert: ' + label;
if(typeof(printStackTrace) == 'function') {
var calls = printStackTrace();
text += '\n' + calls[3];
@ -415,6 +427,11 @@ var Utils = {
isJQuery: function(object) {
// TODO: need more robust way
return (object && typeof(object.fadeIn) == 'function' ? true : false);
},
isDOMElement: function(object) {
// TODO: need more robust way
return (object && typeof(object.tagName) != 'undefined' ? true : false);
}
};

View File

@ -110,6 +110,7 @@ body {
overflow: hidden;
}
.stacked {padding:0;}
.stacked .tab-title{ display: none; }
.stacked .thumbShadow{display: none;}
.stacked .thumb{-moz-box-shadow: rgba(0,0,0,.2) 1px 1px 6px;}

View File

@ -23,7 +23,7 @@
<script type="text/javascript;version=1.8" src="../../js/optional/stacktrace.js"></script>
<script type="text/javascript;version=1.8" src="../../js/core/jquery.js"></script>
<script type="text/javascript;version=1.8" src="../../js/optional/jquery-tabcandy-easing.js"></script>
<script type="text/javascript;version=1.8" src="../../js/optional/jquery.lint.js"></script>
<!-- <script type="text/javascript;version=1.8" src="../../js/optional/jquery.lint.js"></script> -->
<script type="text/javascript;version=1.8" src="../../js/optional/jquery-ui.js"></script>
<script type="text/javascript;version=1.8" src="../../js/core/utils.js"></script>
<script type="text/javascript;version=1.8" src="js/storage.js"></script>