+ Moved my work on the stacks candy to the ian1 candy, and added groups to it

+ added automatic thumbnail repainting for resized thumbnails
+ updated the original and ian1 candies so the thumbnail scales automatically with the jquery animation of the whole tab
This commit is contained in:
Ian Gilman 2010-03-17 14:06:07 -07:00
parent 59ccf4f8de
commit f4fa5c8cca
6 changed files with 365 additions and 45 deletions

View File

@ -82,7 +82,7 @@ Group.prototype = {
this._children = this._children.filter(function(child){
if( $(child).data("toRemove") == true ){
$(child).data("group", null);
$(child).animate({width:160, height:120}, 250);
$(child).animate({width:160, height:137}, 250);
$(child).droppable("enable");
return false;
}
@ -121,9 +121,11 @@ Group.prototype = {
// This is for actual tabs. Need a better solution.
// One that doesn't require special casing to find the linked info.
// If I just animate the tab, the rest should happen automatically!
/*
if( $("canvas", tab)[0] != null ){
$("canvas", tab).data('link').animate({height:h}, 250);
}
*/
$(tab).animate({
height:h, width: w,

View File

@ -50,8 +50,8 @@ TabCanvas.prototype = {
var $canvas = $(this.canvas);
var ctx = this.canvas.getContext("2d");
var w = $canvas.width();
var h = $canvas.height();
var w = $canvas.attr('width');
var h = $canvas.attr('height');
var fromWin = this.tab.contentWindow;
if(fromWin == null) {
@ -78,10 +78,8 @@ TabCanvas.prototype = {
},
animate: function(options, duration){
/*
if(this.tab.contentWindow == null || this.tab.contentWindow.location.protocol != 'chrome:')
Utils.log('on animate', this.tab.contentWindow.location.href);
*/
Utils.log('on animate', this.tab.contentWindow.location.href);
var self = this;
if( duration == null ) duration = 0;
@ -145,6 +143,7 @@ TabMirror.prototype = {
var label = tab.raw.label;
$fav = $(mirror.favEl);
$name = $(mirror.nameEl);
$canvas = $(mirror.canvasEl);
if(iconUrl != $fav.attr("src")) {
$fav.attr("src", iconUrl);
@ -160,6 +159,16 @@ TabMirror.prototype = {
mirror.url = tab.url;
mirror.triggerPaint();
}
var w = $canvas.width();
var h = $canvas.height();
if(w != $canvas.attr('width') || h != $canvas.attr('height')) {
Utils.log(w, $canvas.attr('width'), h, $canvas.attr('height'));
$canvas.attr('width', w);
$canvas.attr('height', h);
mirror.triggerPaint();
}
if(mirror.needsPaint) {
mirror.tabCanvas.paint();

View File

@ -20,6 +20,8 @@
margin: 0px;
padding: 0;
background-color: rgba(255,255,255,.8);
width: 160px;
height: 137px;
}
.fav{
@ -31,10 +33,10 @@
padding: 3px;
-moz-box-shadow: 1px 1px 3px rgba(0,0,0,.2);
}
.thumb{
width: 160px;
height: 120px;
width: 100%;
height: 80%;
background-color: #ccc;
-moz-box-shadow: 1px 1px 10px rgba(0,0,0,.3);
}
@ -43,6 +45,10 @@
-moz-box-shadow: 1px 1px 10px rgba(0,0,0,.5);
}
.thumb-selected {
-moz-box-shadow: 1px 1px 10px rgba(0,0,0,1);
}
.name{
position: absolute;
top: 123px;
@ -82,7 +88,7 @@
}
.search{width:100%; margin-top: 30px; text-align: center; margin-bottom: 30px;}
.search{width:100%; margin-top: 15px; text-align: center; margin-bottom: 30px;}
.search input{ width: 300px; font-size: 16pt;}
#actions{
@ -101,34 +107,66 @@
z-index: -100;
}
.lasso-menu {
background-color: white;
width: 100px;
height: 200px;
border: 1px solid #DDD;
-moz-box-shadow: 2px 2px 4px rgba(0,0,0,.5);
line-height: 100px;
text-align: center;
cursor: pointer;
}
.group{
cursor: move;
-moz-box-shadow: 0px 0px 5px rgba(0,0,0,.2);
}
</style>
</head>
<body>
<div class="search">
<input type="text"/>
</div>
<div id="actions">
<a id="tabbar" class="action" href="#">Toggle Tab Bar</a>
<div id="nav">
<div class="search">
<input type="text"/>
</div>
<div id="actions">
<a id="tabbar" class="action" href="#">Toggle Tab Bar</a>
</div>
</div>
<script type="text/javascript;version=1.8">
</script>
<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-ui.js"></script>
<script type="text/javascript;version=1.8" src="../../js/core/utils.js"></script>
<script type="text/javascript;version=1.8">
Utils.log('it begins');
/* Utils.testLogging(); */
</script>
<script type="text/javascript;version=1.8" src="../../js/core/tabs.js"></script>
<script type="text/javascript;version=1.8" src="../../js/core/mirror.js"></script>
<script type="text/javascript;version=1.8" src="js/ui.js"></script>
<script type="text/javascript;version=1.8" src="../../js/shared/jquery.lasso.js"></script>
<script type="text/javascript;version=1.8" src="js/jquery.select.js"></script>
<script type="text/javascript;version=1.8" src="../zoomgroups/js/groups.js"></script>
<!-- BEGIN Switch Control -->
<script type="text/javascript;version=1.8" src="../../js/optional/switch.js"></script>
<script type="text/javascript;version=1.8">
Switch.insert('body', '');
Switch.insert('#nav', '');
</script>
<!-- END Switch Control -->
<script type="text/javascript;version=1.8">
/* Utils.log(1, Tabs); */
/* window.setTimeout(function() { alert('foo'); }, 2000); */
</script>
</body>
</html>

View File

@ -0,0 +1,138 @@
function Selector(options){ this.init(options) }
Selector.prototype = {
init: function(options){
var self = this;
options.onSelect = function(a,b){
self.showMenu(a,b);
TabMirror.resumePainting();
};
options.onStart = function(){
self.hideMenu(250);
TabMirror.pausePainting();
};
/* options.onMove = function(a){ self.updateSelection(a) }; */
options.acceptMouseDown = function(a){ return self.acceptMouseDown(a); };
this.lasso = new Lasso(options);
},
startFadeOutTimer: function() {
var self = this;
this.timeout = setTimeout(function() {
self.timeout = null;
self.hideMenu(2000);
}, 1000);
},
cancelFadeOutTimer: function() {
if(this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
},
hideMenu: function(time) {
var self = this;
if(this.menu) {
this.menu.fadeOut(time, function() {
if(self.menu) {
self.menu.remove();
self.menu = null;
self.clearSelection();
}
});
}
this.cancelFadeOutTimer();
},
showMenu: function( selectedEls, pos ){
if( pos == null || selectedEls.length == 0 ) return;
var self = this;
this.selectedEls = selectedEls;
this.updateSelection();
this.cancelFadeOutTimer();
this.menu = $("<div class='lasso-menu'>").appendTo("body");
this.menu.css({
position:"fixed",
zIndex: 9999,
top:pos.y-this.menu.height()/2,
left:pos.x-this.menu.width()/2
});
this.menu.mouseover(function() {
self.menu.stop();
self.menu.css({'opacity':1});
self.cancelFadeOutTimer();
});
this.menu.mouseout(function() {
self.startFadeOutTimer();
});
$('<div>Group</div>')
.appendTo(this.menu)
.mousedown(function() {
group(selectedEls);
});
$('<div>Close</div>')
.appendTo(this.menu)
.mousedown(function() {
close(selectedEls);
});
},
updateSelection: function() {
for( var i=0; i<this.selectedEls.length; i++){
var el = this.selectedEls[i];
$('.thumb', el).addClass('thumb-selected');
}
},
clearSelection: function() {
for( var i=0; i<this.selectedEls.length; i++){
var el = this.selectedEls[i];
$('.thumb', el).removeClass('thumb-selected');
}
},
acceptMouseDown: function(e) {
if( $(e.target).is('#nav')
|| $(e.target).parents('#nav').length > 0)
return false;
return true;
}
}
function group(els){
var startEl = $(els[0]);
startEl.css("z-index", 0);
for( var i=1; i<els.length; i++){
var el = els[i];
var pos = startEl.position();
$(el).css("z-index", i*10);
TabMirror.pausePainting();
$(el).animate({top: pos.top, left: pos.left, position: "absolute"}, 500, null, function() {
TabMirror.resumePainting();
});
}
}
function close(els){
for( var i=0; i<els.length; i++){
var el = els[i];
var tab = Tabs.tab(el);
tab.close();
}
}
$(function(){
var select = new Selector({
targets: ".tab",
container: "html",
});
});

View File

@ -22,25 +22,17 @@ var Tabbar = {
var Page = {
init: function(){
var isDragging = false;
var zIndex = 100;
function mod($div){
Utils.log("hi!")
$div.draggable({
start:function(){ isDragging = true; },
stop: function(){
isDragging = false;
$(this).css({zIndex: zIndex});
zIndex += 1;
},
zIndex: 999,
}).mouseup(function(e){
function mod($div, tab){
if(window.Groups) {
$div.draggable(window.Groups.dragOptions);
$div.droppable(window.Groups.dropOptions);
}
$div.mouseup(function(e){
if( e.target.className == "close" ){
$(this).find("canvas").data("link").tab.close(); }
else {
if( !isDragging ){
if(!$(this).data('isDragging')) {
Navbar.show();
$(this).find("canvas").data("link").tab.focus();
} else {
@ -49,8 +41,12 @@ var Page = {
}
});
$("<div class='close'>x</div>").appendTo($div)
$("<div class='close'>x</div>").appendTo($div);
if(Arrange.initialized) {
var p = Page.findOpenSpaceFor($div);
$div.css({left: p.x, top: p.y});
}
}
window.TabMirror.customize(mod);
@ -120,6 +116,92 @@ var Page = {
$(window).blur(function(){
Navbar.show();
})
},
findOpenSpaceFor: function($div) {
var w = window.innerWidth;
var h = 0;
var startX = 30;
var startY = 100;
var bufferX = 30;
var bufferY = 30;
var rects = [];
var r;
var $el;
$(".tab:visible").each(function(i) {
if(this == $div.get(0))
return;
$el = $(this);
r = {x: parseInt($el.css('left')),
y: parseInt($el.css('top')),
w: parseInt($el.css('width')) + bufferX,
h: parseInt($el.css('height')) + bufferY};
if(r.x + r.w > w)
w = r.x + r.w;
if(r.y + r.h > h)
h = r.y + r.h;
rects.push(r);
});
if(!h)
return { 'x': startX, 'y': startY };
var canvas = document.createElement('canvas');
$(canvas).attr({width:w,height:h});
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgb(255, 255, 255)';
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = 'rgb(0, 0, 0)';
var count = rects.length;
var a;
for(a = 0; a < count; a++) {
r = rects[a];
ctx.fillRect(r.x, r.y, r.w, r.h);
}
var divWidth = parseInt($div.css('width')) + bufferX;
var divHeight = parseInt($div.css('height')) + bufferY;
var strideX = divWidth / 4;
var strideY = divHeight / 4;
var data = ctx.getImageData(0, 0, w, h).data;
function isEmpty(x1, y1) {
return (x1 >= 0 && y1 >= 0
&& x1 < w && y1 < h
&& data[(y1 * w + x1) * 4]);
}
function isEmptyBox(x1, y1) {
return (isEmpty(x1, y1)
&& isEmpty(x1 + (divWidth - 1), y1)
&& isEmpty(x1, y1 + (divHeight - 1))
&& isEmpty(x1 + (divWidth - 1), y1 + (divHeight - 1)));
}
for(var y = startY; y < h; y += strideY) {
for(var x = startX; x < w; x += strideX) {
if(isEmptyBox(x, y)) {
for(; y > startY + 1; y--) {
if(!isEmptyBox(x, y - 1))
break;
}
for(; x > startX + 1; x--) {
if(!isEmptyBox(x - 1, y))
break;
}
return { 'x': x, 'y': y };
}
}
}
return { 'x': startX, 'y': h };
}
}
@ -162,8 +244,12 @@ var grid = new ArrangeClass("Grid", function(value) {
if(immediately)
$el.css({top: y,left: x});
else
$el.animate({top: y,left: x}, 1000);
else {
TabMirror.pausePainting();
$el.animate({top: y,left: x}, 500, null, function() {
TabMirror.resumePainting();
});
}
x += $el.width() + 30;
if( x > window.innerWidth - ($el.width() + startX)){ // includes allowance for the box shadow
@ -175,17 +261,64 @@ var grid = new ArrangeClass("Grid", function(value) {
//----------------------------------------------------------
var stack = new ArrangeClass("Stack", function() {
var x = 30;
var y = 100;
var startX = 30;
var startY = 100;
var x = startX;
var y = startY;
$(".tab:visible").each(function(i){
$el = $(this);
$el.animate({'top': y, 'left': x, '-moz-transform': 'rotate(40deg)'}, 1000);
TabMirror.pausePainting();
$el.animate({'top': y, 'left': x, '-moz-transform': 'rotate(40deg)'}, 500, null, function() {
TabMirror.resumePainting();
});
});
});
//----------------------------------------------------------
var site = new ArrangeClass("Site", function() {
var startX = 30;
var startY = 100;
var x = startX;
var y = startY;
var x2;
var y2;
var positions = [];
$(".tab:visible").each(function(i) {
$el = $(this);
var tab = Tabs.tab(this);
var url = tab.url;
var domain = url.split('/')[2];
var domainParts = domain.split('.');
var mainDomain = domainParts[domainParts.length - 2];
if(positions[mainDomain]) {
x2 = positions[mainDomain].x;
y2 = positions[mainDomain].y;
} else {
x2 = x;
y2 = y;
x += $el.width() + 30;
if( x > window.innerWidth - ($el.width() + startX)){ // includes allowance for the box shadow
x = startX;
y += $el.height() + 30;
}
positions[mainDomain] = { 'x': x2, 'y': y2 };
}
TabMirror.pausePainting();
$el.animate({'top': y2, 'left': x2, '-moz-transform': 'rotate(40deg)'}, 500, null, function() {
TabMirror.resumePainting();
});
});
});
//----------------------------------------------------------
var Arrange = {
initialized: false,
init: function(){
this.initialized = true;
grid.arrange(true);
}
}
@ -198,14 +331,12 @@ UIClass.prototype = {
init: function(){
Page.init();
Arrange.init();
}
}
//----------------------------------------------------------
var UI = new UIClass();
window.UI = UI;
//window.aza = ArrangeClass
})();

View File

@ -21,6 +21,8 @@
padding: 0;
background-color: rgba(255,255,255,.8);
z-index: 0;
width: 160px;
height: 137px;
}
.fav{
@ -34,8 +36,8 @@
}
.thumb{
width: 160px;
height: 120px;
width: 100%;
height: 80%;
background-color: #ccc;
-moz-box-shadow: 1px 1px 10px rgba(0,0,0,.3);
}