oxjs/source/Ox.UI/js/Window/Ox.Dialog.js
2011-05-16 10:24:46 +02:00

398 lines
12 KiB
JavaScript

// vim: et:ts=4:sw=4:sts=4:ft=js
/*@
Ox.Dialog <f:Ox.Element> Dialog Object
() -> <f> Dialog Object
(options) -> <f> Dialog Object
(options, self) -> <f> Dialog Object
options <o> Options object
self <o> shared private variable
@*/
Ox.Dialog = function(options, self) {
// fixme: dialog should be derived from a generic draggable
// fixme: buttons should have a close attribute, or the dialog a close id
var self = self || {},
that = new Ox.Element({}, self)
.defaults({
title: '',
buttons: [],
content: null,
height: 216,
keys: {},
minHeight: 144,
minWidth: 256,
movable: true,
padding: 16,
resizable: true,
width: 384
})
.options(options || {})
.addClass('OxDialog')
.bindEvent({
key_enter: function() {
keypress('enter');
},
key_escape: function() {
//Ox.print('KEY ESCAPE')
keypress('escape');
}
});
$.extend(self, {
initialWidth: self.options.width,
initialHeight: self.options.height
})
that.$titlebar = new Ox.Bar({
size: 'medium'
})
.addClass('OxTitleBar')
.appendTo(that);
self.options.movable && that.$titlebar
.dblclick(center)
.bindEvent({
dragstart: dragstart,
drag: drag
});
that.$title = new Ox.Element()
.addClass('OxTitle')
.html(self.options.title)
.appendTo(that.$titlebar);
that.$content = new Ox.Element()
.addClass('OxContent')
.css({
padding: self.options.padding + 'px',
overflow: 'auto'
})
.append(self.options.content)
.appendTo(that);
that.$buttonsbar = new Ox.Bar({})
.addClass('OxButtonsBar')
.appendTo(that);
loadButtons();
//that.$buttons[0].focus();
that.$layer = new Ox.Element() // fixme: Layer widget that would handle click?
.addClass('OxLayer')
.mousedown(mousedownLayer)
.mouseup(mouseupLayer);
function center() {
var documentHeight = Ox.UI.$document.height();
that.css({
left: 0,
top: Math.max(parseInt(-documentHeight / 10), self.options.height - documentHeight + 40) + 'px',
right: 0,
bottom: 0,
margin: 'auto'
});
}
function dragstart(event, e) {
self.drag = {
bodyWidth: Ox.UI.$body.width(),
bodyHeight: Ox.UI.$document.height(),
elementWidth: that.width(),
offset: that.offset(),
x: e.clientX,
y: e.clientY
};
that.css({
margin: 0
});
}
function drag(event, e) {
var left = Ox.limit(
self.drag.offset.left - self.drag.x + e.clientX,
24 - self.drag.elementWidth, self.drag.bodyWidth - 24
//0, self.drag.documentWidth - self.drag.elementWidth
),
top = Ox.limit(
self.drag.offset.top - self.drag.y + e.clientY,
24, self.drag.bodyHeight - 24
//24, self.drag.documentHeight - self.drag.elementHeight
);
that.css({
left: left + 'px',
top: top + 'px'
});
}
function dragstartResize(event, e) {
self.drag = {
documentWidth: Ox.UI.$document.width(),
documentHeight: Ox.UI.$document.height(),
elementWidth: that.width(),
elementHeight: that.height(),
offset: that.offset(),
x: e.clientX,
y: e.clientY
};
$.extend(self.drag, {
ratio: self.drag.elementWidth / self.drag.elementHeight
});
that.css({
left: self.drag.offset.left,
top: self.drag.offset.top,
margin: 0
});
}
function dragResize(event, e) {
if (!e.shiftKey) {
self.drag.ratio = self.options.width / self.options.height;
}
self.options.width = Ox.limit(
self.drag.elementWidth - self.drag.x + e.clientX,
self.options.minWidth,
Math.min(
self.drag.documentWidth,
self.drag.documentWidth - self.drag.offset.left
)
);
self.options.height = Ox.limit(
self.drag.elementHeight - self.drag.y + e.clientY,
self.options.minHeight,
Math.min(
self.drag.documentHeight,
self.drag.documentHeight - self.drag.offset.top
)
);
if (e.shiftKey) {
self.options.height = Ox.limit(
self.options.width / self.drag.ratio,
self.options.minHeight,
Math.min(
self.drag.documentHeight,
self.drag.documentHeight - self.drag.offset.top
)
);
self.options.width = self.options.height * self.drag.ratio;
}
that.width(self.options.width);
that.height(self.options.height);
that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically
}
function dragendResize(event, e) {
triggerResizeEvent();
}
function getButtonById(id) {
var ret = null;
//Ox.print('that.$buttons', that.$buttons, id)
Ox.forEach(that.$buttons, function(button) {
if (button.options('id') == id) {
ret = button;
return false;
}
});
return ret;
}
function keypress(key) {
var id = self.options.keys[key];
//Ox.print('X', key, self.options.keys)
id && getButtonById(id).$element.trigger('click');
}
function loadButtons() {
/*Ox.print('loadButtons', $.map(self.options.buttons, function(v) {
return v;
}));*/
if (that.$buttons) {
that.$buttons.forEach(function($button) {
$button.removeElement();
});
that.$resize.removeElement();
// that.$buttonsbar.empty();
}
that.$buttons = [];
if (!Ox.isArray(self.options.buttons[0])) {
self.options.buttons = [[], self.options.buttons];
}
self.options.buttons[0].forEach(function(button, i) {
that.$buttons[i] = button
.addClass('OxLeft')
.appendTo(that.$buttonsbar);
});
if (self.options.resizable) {
that.$resize = new Ox.Element()
.addClass('OxResize')
.dblclick(reset)
.bindEvent({
dragstart: dragstartResize,
drag: dragResize,
dragend: dragendResize
})
.appendTo(that.$buttonsbar);
}
self.options.buttons[1].reverse().forEach(function(button) {
that.$buttons[that.$buttons.length] = button
.addClass('OxRight')
.appendTo(that.$buttonsbar);
});
}
function mousedownLayer() {
that.$layer.stop().animate({
opacity: 0.5
}, 0);
}
function mouseupLayer() {
that.$layer.stop().animate({
opacity: 0
}, 0);
}
function reset() {
$.extend(self.options, {
height: self.initialHeight,
width: self.initialWidth
});
that/*.css({
left: Math.max(that.offset().left, 24 - that.width())
})*/
.width(self.options.width)
.height(self.options.height);
that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically
triggerResizeEvent();
}
function triggerResizeEvent() {
that.triggerEvent('resize', {
width: self.options.width,
height: self.options.height
});
}
self.setOption = function(key, value) {
if (key == 'buttons') {
loadButtons();
/*
that.$buttonsbar.children().animate({
opacity: 0
}, 100, function() {
loadButtons();
that.$buttonsbar.children().animate({
opacity: 1
}, 100);
});
*/
} else if (key == 'content') {
that.$content.html(value);
} else if (key == 'height' || key == 'width') {
that.animate({
height: self.options.height + 'px',
width: self.options.width + 'px'
}, 100);
that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically
} else if (key == 'title') {
that.$title.animate({
opacity: 0
}, 100, function() {
that.$title.html(value).animate({
opacity: 1
}, 100);
});
}
}
that.center = function() {
};
that.close = function(callback) {
callback = callback || function() {};
that.animate({
opacity: 0
}, 200, function() {
that.$buttons.forEach(function($button) {
$button.removeElement();
});
that.loseFocus();
that.$layer.removeElement();
that.removeElement();
callback();
});
Ox.UI.$window.unbind('mouseup', mouseupLayer)
return that;
};
that.content = function($element) {
that.$content.empty().append($element);
return that;
}
that.disable = function() {
// to be used on submit of form, like login
that.$layer.addClass('OxFront');
return that;
};
that.disableButton = function(id) {
getButtonById(id).options({
disabled: true
});
return that;
};
that.enable = function() {
that.$layer.removeClass('OxFront');
return that;
};
that.enableButton = function(id) {
getButtonById(id).options({
disabled: false
});
return that;
};
that.open = function() {
//Ox.print('before open')
that.$layer.appendTo(Ox.UI.$body);
that.css({
opacity: 0
}).appendTo(Ox.UI.$body).animate({
opacity: 1
}, 200);
center();
reset();
// fixme: the following line prevents preview-style dialog
that.gainFocus();
Ox.UI.$window.bind('mouseup', mouseupLayer)
//Ox.print('after open')
return that;
};
that.size = function(width, height, callback) {
$.extend(self, {
initialWidth: width,
initialHeight: height
});
$.extend(self.options, {
width: width,
height: height
});
// fixme: duplicated
that.animate({
height: self.options.height + 'px',
width: self.options.width + 'px'
}, 100, function() {
that.$content.height(self.options.height - 48 - 2 * self.options.padding); // fixme: this should happen automatically
callback();
});
}
return that;
};