Implemented Hero-dialog editing of features

This commit is contained in:
Thaum
2015-01-30 10:14:46 +00:00
parent 848902c358
commit 37e8831e0c
14 changed files with 242 additions and 105 deletions

View File

@@ -223,8 +223,8 @@ var attributeBase = function(charId, statName){
//start with the highest base value
_.each(effects.base, function(effect){
var efv = evaluateEffect(charId, effect)
if (effect.value > value){
value = effect.value;
if (efv > value){
value = efv;
}
});

View File

@@ -13,9 +13,9 @@
"tests"
],
"dependencies": {
"polymer": "Polymer/polymer#~0.5.2",
"core-elements": "Polymer/core-elements#~0.5.2",
"paper-elements": "Polymer/paper-elements#~0.5.2",
"polymer": "Polymer/polymer#~0.5.4",
"core-elements": "Polymer/core-elements#~0.5.4",
"paper-elements": "Polymer/paper-elements#~0.5.4",
"paper-fab-menu": "cwdoh/paper-fab-menu"
},
"resolutions": {

View File

@@ -9,7 +9,7 @@ this.GlobalUI = (function() {
toast.text = text;
return toast.show();
};
GlobalUI.setDialog = function(opts){
this.dialog = $("[global-dialog]")[0];
Session.set("global.ui.dialogHeader", opts.heading);
@@ -30,6 +30,33 @@ this.GlobalUI = (function() {
};
})(this));
};
//To show a detail, first animate the click, with raising z-depth
//then call this function with a template and data
//the element should have a hero-id of detail-main
GlobalUI.showDetail = function(opts) {
Session.set("global.ui.detailData", opts.data);
Session.set("global.ui.detailTemplate", opts.template);
GlobalUI.detailHero = opts.hero;
Session.set("global.ui.detailShow", true);
};
//if setting the detail rather than showing it,
//the template should contain the following in template.rendered
//
//if (!this.alreadyRendered){
// Session.set("global.ui.detailShow", true);
// this.alreadyRendered = true;
//}
GlobalUI.setDetail = function(opts) {
Session.set("global.ui.detailData", opts.data);
Session.set("global.ui.detailTemplate", opts.template);
GlobalUI.detailHero = opts.hero;
};
GlobalUI.closeDetail = function(){
Session.set("global.ui.detailShow", false);
};
GlobalUI.closeDialog = function() {
return this.dialog.close();
@@ -51,6 +78,15 @@ Template.layout.helpers({
},
globalDialogHeader: function(){
return Session.get("global.ui.dialogHeader");
},
globalDetailSelected: function(){
return Session.get("global.ui.detailShow") ? 1 : 0;
},
globalDetailTemplate: function(){
return Session.get("global.ui.detailTemplate");
},
globalDetailData: function(){
return Session.get("global.ui.detailData");
}
});
@@ -60,4 +96,37 @@ Template.layout.events({
Session.set("global.ui.dialogData", null);
return Session.set("global.ui.dialogFullOnMobile", null);
},
"core-animated-pages-transition-end [detail-pages]": function(e) {
var detailOpened = Session.get("global.ui.detailShow");
if(detailOpened){
//HACK by putting core-selected back on the main content section
//we stop it being hidden while the detail section is shown
$("#mainContentSection").addClass("core-selected");
//but we still want to track whether it is or isn't actually selected
//so we can hide hero elements, since they are technically now shown as detail
$("#mainContentSection").addClass("fake-selected");
} else {
Session.set("global.ui.detailData", null);
Session.set("global.ui.detailTemplate", null);
//remove the hero attribute
var heroElem = GlobalUI.detailHero;
heroElem && heroElem.attr("hero", null);
heroElem && heroElem.find("[hero-id]").attr("hero", null);
GlobalUI.detailHero = null;
}
},
"core-animated-pages-transition-prepare": function(e) {
var detailOpened = Session.get("global.ui.detailShow");
if(detailOpened) {
//add the hero attribute where needed
var heroElem = GlobalUI.detailHero;
heroElem && heroElem.attr("hero", "");
heroElem && heroElem.find("[hero-id]").attr("hero", "");
} else {
$("#mainContentSection").removeClass("fake-selected");
}
},
"tap #screenDim": function(e){
GlobalUI.closeDetail();
}
});

View File

@@ -0,0 +1,33 @@
#detailScreenFiller {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
}
#screenDim {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: black;
opacity: 0.0;
}
#globalDetail {
background-color: white;
width: 624px;
height: 500px;
}
.fake-selected [hero] {
visibility: hidden;
}

View File

@@ -43,6 +43,9 @@ Template.characterSheet.events({
"swiperight": function(event){
incTab(Template.instance(), -1);
},
"core-animated-pages-transition-end #tabPages": function(event) {
event.stopPropagation();
}
});
/* requires the following templates

View File

@@ -22,7 +22,7 @@ html /deep/ paper-input {
margin-bottom: 1px;
}
html /deep/ .featureEffect {
html /deep/ .effectEdit {
display: flex;
align-items: flex-end;
}

View File

@@ -1,20 +1,20 @@
<template name="effectEdit">
<div class="effectEdit">
<paper-dropdown-menu id="statGroupDropDown" label="Stat Group">
<paper-dropdown class="dropdown">
<paper-dropdown layered class="dropdown">
<core-menu id="statGroupMenu" class="menu" selected={{selectedStatGroup}}>
{{#each statGroups}}
<paper-item class="statGroupSelect">{{this}}</paper-item>
<paper-item class="statGroupSelect" name={{this}}>{{this}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
{{#if stats}}
<paper-dropdown-menu id="statDropDown" label="Stat">
<paper-dropdown class="dropdown">
<core-menu id="statMenu" class="menu" selected={{selectedStat}}>
<paper-dropdown layered class="dropdown">
<core-menu id="statMenu" class="menu" selected={{selectedStat}} on-tap="onStatMenuTap">
{{#each stats}}
<paper-item>{{name}}</paper-item>
<paper-item name={{stat}}>{{name}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
@@ -22,10 +22,10 @@
{{/if}}
{{#if operations}}
<paper-dropdown-menu id="operationDropDown" label="Operation">
<paper-dropdown class="dropdown">
<paper-dropdown layered class="dropdown">
<core-menu id="operationMenu" class="menu" selected={{selectedOperation}}>
{{#each operations}}
<paper-item>{{name}}</paper-item>
<paper-item name={{operation}}>{{name}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
@@ -48,11 +48,11 @@
<template name="multiplierEffectValue">
<paper-dropdown-menu id="damageMultiplierDropDown" label="Damage Multiplier">
<paper-dropdown class="dropdown">
<paper-dropdown layered class="dropdown">
<core-menu id="multiplierMenu" class="menu" selected={{selectedDamageMultiplier}}>
<paper-item>Resistance</paper-item>
<paper-item>Vulnerability</paper-item>
<paper-item>Immunity</paper-item>
<paper-item name="resistance">Resistance</paper-item>
<paper-item name="vulnerability">Vulnerability</paper-item>
<paper-item name="immunity">Immunity</paper-item>
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
@@ -60,11 +60,11 @@
<template name="proficiencyEffectValue">
<paper-dropdown-menu id="proficiencyDropDown" label="Proficiency">
<paper-dropdown class="dropdown">
<paper-dropdown layered class="dropdown">
<core-menu id="proficiencyMenu" class="menu" selected={{selectedProfiencyMultiplier}}>
<paper-item>Proficient</paper-item>
<paper-item>Half Prof. Bonus</paper-item>
<paper-item>Double Prof. Bonus</paper-item>
<paper-item name="proficient">Proficient</paper-item>
<paper-item name="half">Half Prof. Bonus</paper-item>
<paper-item name="double">Double Prof. Bonus</paper-item>
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>

View File

@@ -188,14 +188,14 @@ Template.effectEdit.helpers({
//resistance/vulnerability template
var group = Template.instance().selectedStatGroup.get();
if(group === "Weakness/Resistance") return "multiplierEffectValue";
var op = Template.instance().selectedOperation.get();
if(!op) return null;
//operations that don't need templates
if(op === "advantage" || op === "disadvantage" || op === "fail") return null;
//proficiency template
if(op === "proficiency") return "proficiencyEffectValue";
//default template
return "regularEffectValue";
},
@@ -265,71 +265,58 @@ Template.effectEdit.events({
"tap #deleteEffect": function(event){
Effects.remove(this._id);
},
"core-select #statGroupMenu": function(event){
var groupMenu = Template.instance().find("#statGroupMenu")
if(!groupMenu) return;
var groupIndex = groupMenu.selected;
var groupName = statGroupNames[groupIndex]
"core-select #statGroupDropDown": function(event){
var detail = event.originalEvent.detail;
if(!detail.isSelected) return;
var groupName = detail.item.getAttribute("name");
var oldName = Template.instance().selectedStatGroup.get();
if(oldName != groupName){
Template.instance().selectedStatGroup.set(groupName);
var oldIndex = statGroupIndex(Template.instance().selectedStat.get())
var oldIndex = statGroupIndex(Template.instance().selectedStat.get());
var groupIndex = statGroupIndex(groupName);
if(oldIndex != groupIndex){
Template.instance().selectedStat.set(null);
}
}
},
"core-select #statMenu": function(event){
var statMenu = Template.instance().find("#statMenu");
var groupMenu = Template.instance().find("#statGroupMenu");
if(!statMenu || !groupMenu) return;
var statIndex = statMenu.selected;
var groupIndex = groupMenu.selected;
var groupName = statGroupNames[groupIndex]
var group = statGroups[groupName];
var statObj = group[statIndex];
if(!statObj) return;
var statName = statObj.stat;
"core-select #statDropDown": function(event){
var detail = event.originalEvent.detail;
if(!detail.isSelected) return;
var statName = detail.item.getAttribute("name");
Template.instance().selectedStat.set(statName);
},
"core-select #operationMenu": function(event){
var groupName = Template.instance().selectedStatGroup.get();
var opGroup = (groupName === "Saving Throws" || groupName === "Skills")? skillOperations : attributeOperations;
var opMenu = Template.instance().find("#operationMenu")
if(!opMenu) return;
var opIndex = opMenu.selected;
var op = opGroup[opIndex];
if(!op) return;
var opName = op.operation;
"core-select #operationDropDown": function(event){
var detail = event.originalEvent.detail;
if(!detail.isSelected) return;
var opName = detail.item.getAttribute("name");
Template.instance().selectedOperation.set(opName);
},
"core-select #multiplierMenu": function(event){
"core-select #damageMultiplierDropDown": function(event){
var detail = event.originalEvent.detail;
if(!detail.isSelected) return;
var selected = detail.item.getAttribute("name");
var inst = Template.instance();
var mulMenu = Template.instance().find("#multiplierMenu");
if(!mulMenu) return;
var selected = mulMenu.selected;
if(selected === 0){
if(selected === "resistance"){
inst.value.set(0.5);
inst.selectedOperation.set("mul");
} else if (selected === 1){
} else if (selected === "vulnerability"){
inst.value.set(2);
inst.selectedOperation.set("mul");
} else if (selected === 2){
} else if (selected === "immunity"){
inst.value.set(0);
inst.selectedOperation.set("max");
}
},
"core-select #proficiencyMenu": function(event){
"core-select #proficiencyDropDown": function(event){
var detail = event.originalEvent.detail;
if(!detail.isSelected) return;
var selected = detail.item.getAttribute("name");
var inst = Template.instance();
var profMenu = inst.find("#proficiencyMenu");
if(!profMenu) return;
var selected = profMenu.selected;
var value;
if(selected === 0){
if(selected === "proficient"){
inst.value.set(1);
} else if (selected === 1){
} else if (selected === "half"){
inst.value.set(0.5);
} else if (selected === 2){
} else if (selected === "double"){
inst.value.set(2);
}
},

View File

@@ -1,27 +1,32 @@
<template name="featureDialog">
{{#with feature}}
<paper-menu-button>
<paper-icon-button role="button" tabindex="0" icon="delete" aria-label="Delete Feature" noink></paper-icon-button>
<paper-dropdown class="dropdown">
<paper-button id="deleteFeature">Delete Feature</paper-button>
<paper-button>Cancel</paper-button>
</paper-dropdown>
</paper-menu-button>
<div class="featureDialogWidth"></div>
<paper-input id="featureNameInput" label="Name" floatinglabel value={{name}}></paper-input>
<paper-input-decorator label="Description" floatinglabel layout vertical>
<paper-autogrow-textarea>
<textarea id="featureDescriptionInput" placeholder aria-label="Description" value={{description}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<h3>Effects</h3>
{{#each effects}}
{{>effectEdit}}
{{/each}}
<br>
<paper-icon-button id="addEffectButton" role="button" tabindex="0" icon="add" aria-label="addEffect"></paper-icon-button>
<core-header-panel fit>
<core-toolbar>
<paper-icon-button id="backButton" role="button" tabindex="0" icon="arrow-back" aria-label="close"></paper-icon-button>
<div flex>{{name}}</div>
<paper-menu-button>
<paper-icon-button role="button" tabindex="0" icon="delete" aria-label="Delete Feature" noink></paper-icon-button>
<paper-dropdown layered class="dropdown">
<paper-button id="deleteFeature">Delete Feature</paper-button>
<paper-button>Cancel</paper-button>
</paper-dropdown>
</paper-menu-button>
</core-toolbar>
<div class="featureContent">
<paper-input id="featureNameInput" label="Name" floatinglabel value={{name}}></paper-input>
<paper-input-decorator label="Description" floatinglabel layout vertical>
<paper-autogrow-textarea>
<textarea id="featureDescriptionInput" placeholder aria-label="Description" value={{description}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<h3>Effects</h3>
{{#each effects}}
{{>effectEdit}}
{{/each}}
<div layout horizontal end-justified>
<paper-button id="addEffectButton" raised>Add Effect</paper-button>
</div>
</div>
</core-header-panel>
{{/with}}
<paper-button affirmative>Done</paper-button>
</template>

View File

@@ -5,13 +5,19 @@ Template.featureDialog.rendered = function(){
if(feature && feature.name) Session.set("global.ui.dialogHeader", feature.name);
})
//after the dialog is built, open it
_.defer(function(){GlobalUI.dialog.open()});
if (!this.alreadyRendered){
Session.set("global.ui.detailShow", true);
this.alreadyRendered = true;
}
}
Template.featureDialog.events({
"tap #backButton": function(){
GlobalUI.closeDetail()
},
"tap #deleteFeature": function(){
Features.remove(this._id);
GlobalUI.closeDialog()
GlobalUI.closeDetail()
},
"tap #addEffectButton": function(){
Effects.insert({

View File

@@ -1,3 +1,12 @@
body /deep/ .featureDialogWidth {
width: 560px;
}
.featureContent {
padding: 24px;
}
#addEffectButton {
background: #d23f31;
color: #fff;
}

View File

@@ -9,7 +9,7 @@
</div>
<div class="features">
{{#each features}}
<paper-shadow class="featureCard">
<paper-shadow class="featureCard" hero-id="main">
<div class="featureCardTop">
<h2>{{name}}</h2>
</div>
@@ -20,6 +20,13 @@
</div>
<div class="fab-buffer"></div>
</div>
<paper-fab id="addFeature" class="floatyButton" icon="add" title="Add" role="button" tabindex="0" aria-label="Add"></paper-fab>
<paper-fab id="addFeature"
class="floatyButton"
icon="add"
title="Add"
role="button"
tabindex="0"
aria-label="Add"
hero-id="main"></paper-fab>
</div>
</template>

View File

@@ -8,20 +8,18 @@ Template.features.helpers({
Template.features.events({
"tap #addFeature": function(event){
var featureId = Features.insert({name: "New Feature", charId: this._id});
GlobalUI.setDialog({
heading: "New Feature",
template: "featureDialog",
data: {featureId: featureId, charId: this._id},
fullOnMobile: true
GlobalUI.setDetail({
template: "featureDialog",
data: {featureId: featureId, charId: this._id},
hero: $(event.currentTarget)
})
},
"tap .featureCard": function(event){
var featureId = this._id;
GlobalUI.setDialog({
heading: this.name,
template: "featureDialog",
data: {featureId: featureId, charId: Template.parentData()._id},
fullOnMobile: true
GlobalUI.setDetail({
template: "featureDialog",
data: {featureId: featureId, charId: Template.parentData()._id},
hero: $(event.currentTarget)
})
}
});

View File

@@ -8,9 +8,27 @@
<core-item icon="settings" label="item2"></core-item>
</core-menu>
</core-header-panel>
<core-header-panel main navigation flex mode="seamed">
{{> yield}}
</core-header-panel>
<core-animated-pages main
navigation
detail-pages
transitions="hero-transition cross-fade"
selected={{globalDetailSelected}}>
<section id="mainContentSection">
<core-header-panel fit mode="seamed">
{{> yield}}
</core-header-panel>
</section>
<section id="detailSection">
<div id="detailScreenFiller">
<div id="screenDim" cross-fade></div>
<paper-shadow id="globalDetail" z="5" animated hero hero-id="main">
{{#if globalDetailTemplate}}
{{> UI.dynamic template=globalDetailTemplate data=globalDetailData}}
{{/if}}
</paper-shadow>
</div>
</section>
</core-animated-pages>
</core-drawer-panel>
<paper-action-dialog global-dialog backdrop
@@ -25,4 +43,6 @@
</paper-action-dialog>
<paper-toast global-toast></paper-toast>
<core-overlay></core-overlay>
<core-overlay-layer></core-overlay-layer>
</template>