105 lines
3.0 KiB
JavaScript
105 lines
3.0 KiB
JavaScript
dialogs = new ReactiveArray();
|
|
const offset = 16;
|
|
|
|
pushDialogStack = function({template, data, element, callback}){
|
|
// Generate a new _id so that Blaze knows how to shuffle the array
|
|
const _id = Random.id();
|
|
dialogs.push({
|
|
_id,
|
|
template,
|
|
data,
|
|
element,
|
|
callback,
|
|
});
|
|
};
|
|
|
|
popDialogStack = function(result){
|
|
const dialog = dialogs.pop();
|
|
if (!dialog) return;
|
|
dialog.callback && dialog.callback(result);
|
|
};
|
|
|
|
Template.dialogStack.helpers({
|
|
dialogStackStyle(){
|
|
if (!dialogs.get().length) return "display: none;";
|
|
},
|
|
dialogs(){
|
|
return dialogs.get();
|
|
},
|
|
dialogStyle(index){
|
|
const num = dialogs.get().length - 1;
|
|
const left = (num - index) * -offset;
|
|
const top = (num - index) * -offset;
|
|
return `left:${left}px; top:${top}px;`;
|
|
},
|
|
});
|
|
|
|
Template.dialogStack.events({
|
|
"click .dialog-stack": function(event){
|
|
popDialogStack();
|
|
},
|
|
"click .dialog-sizer": function(event){
|
|
// Returning false from an event handler is the same as calling both
|
|
// stopImmediatePropagation and preventDefault on the event.
|
|
return false;
|
|
},
|
|
});
|
|
|
|
Template.dialogStack.uihooks({
|
|
".dialog": {
|
|
container: ".dialog-sizer",
|
|
insert: function(node, next, tpl) {
|
|
$(node).insertBefore(next);
|
|
|
|
const data = Blaze.getData(node);
|
|
if (data.element){
|
|
data.element.style.visibility = "hidden";
|
|
const toRect = node.getBoundingClientRect();
|
|
const fromRect = data.element.getBoundingClientRect();
|
|
const deltaLeft = fromRect.left - toRect.left;
|
|
const deltaTop = fromRect.top - toRect.top;
|
|
const deltaWidth = fromRect.width / toRect.width;
|
|
const deltaHeight = fromRect.height / toRect.height;
|
|
node.style.transition = "none";
|
|
node.style.transform = `translate(${deltaLeft}px, ${deltaTop}px) ` +
|
|
`scale(${deltaWidth}, ${deltaHeight})`;
|
|
node.style.borderRadius = $(data.element).css("border-radius");
|
|
node["data-element"] = data.element;
|
|
_.defer(() => {
|
|
node.style.transition = "";
|
|
node.style.transform = "";
|
|
node.style.borderRadius = "";
|
|
});
|
|
}
|
|
},
|
|
remove: function(node, tpl) {
|
|
//TODO maybe make the element transform to the dialog size
|
|
// and then return to its place?
|
|
const element = node["data-element"];
|
|
if (element){
|
|
const toRect = node.getBoundingClientRect();
|
|
const fromRect = element.getBoundingClientRect();
|
|
let deltaLeft = fromRect.left - toRect.left;
|
|
let deltaTop = fromRect.top - toRect.top;
|
|
const deltaWidth = fromRect.width / toRect.width;
|
|
const deltaHeight = fromRect.height / toRect.height;
|
|
node.style.transform = `translate(${deltaLeft}px, ${deltaTop}px) ` +
|
|
`scale(${deltaWidth}, ${deltaHeight})`;
|
|
node.style.borderRadius = $(element).css("border-radius");
|
|
_.delay(() => {
|
|
element.style.visibility = "";
|
|
node.remove();
|
|
}, 500);
|
|
} else {
|
|
node.remove();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
Template.testDialog.events({
|
|
"click .testButton": function(event, template){
|
|
pushDialogStack({template: "testDialog", element: event.currentTarget, data: Random.id()});
|
|
}
|
|
})
|