diff --git a/Packages/ohif-core/client/components/base/index.js b/Packages/ohif-core/client/components/base/index.js
index b6dcb77d9..c494cd8e8 100644
--- a/Packages/ohif-core/client/components/base/index.js
+++ b/Packages/ohif-core/client/components/base/index.js
@@ -19,6 +19,7 @@ import './mixins/group.js';
import './mixins/groupRadio.js';
import './mixins/input.js';
import './mixins/link.js';
+import './mixins/popover.js';
import './mixins/schemaData.js';
import './mixins/select.js';
import './mixins/select2.js';
diff --git a/Packages/ohif-core/client/components/base/mixins/popover.js b/Packages/ohif-core/client/components/base/mixins/popover.js
new file mode 100644
index 000000000..7c9f729d1
--- /dev/null
+++ b/Packages/ohif-core/client/components/base/mixins/popover.js
@@ -0,0 +1,40 @@
+import { Meteor } from 'meteor/meteor';
+import { Template } from 'meteor/templating';
+import { $ } from 'meteor/jquery';
+import { OHIF } from 'meteor/ohif:core';
+
+/*
+ * popover: controls a popover
+ */
+OHIF.mixins.popover = new OHIF.Mixin({
+ dependencies: 'form',
+ composition: {
+ onRendered() {
+ const instance = Template.instance();
+ instance.$form = instance.$('form').first();
+ instance.$form.find(':input:first').focus();
+ },
+
+ events: {
+ 'blur form'(event, instance) {
+ Meteor.defer(() => {
+ const $focus = $(':focus');
+ if (!$.contains(instance.$form[0], $focus[0])) {
+ instance.data.promiseReject();
+ }
+ });
+ },
+
+ 'click .btn-cancel'(event, instance) {
+ event.stopPropagation();
+ instance.data.promiseReject();
+ },
+
+ 'click .btn-confirm'(event, instance) {
+ event.stopPropagation();
+ const form = instance.$('form').data('component');
+ instance.data.promiseResolve(form.value());
+ }
+ }
+ }
+});
diff --git a/Packages/ohif-core/client/components/bootstrap/index.js b/Packages/ohif-core/client/components/bootstrap/index.js
index 2de8cc008..1e4fc3db5 100644
--- a/Packages/ohif-core/client/components/bootstrap/index.js
+++ b/Packages/ohif-core/client/components/bootstrap/index.js
@@ -31,3 +31,5 @@ import './input/radio.html';
import './input/range.html';
import './input/select.html';
import './input/text.html';
+
+import './popover/form.html';
diff --git a/Packages/ohif-core/client/components/bootstrap/popover/form.html b/Packages/ohif-core/client/components/bootstrap/popover/form.html
new file mode 100644
index 000000000..ace107a75
--- /dev/null
+++ b/Packages/ohif-core/client/components/bootstrap/popover/form.html
@@ -0,0 +1,17 @@
+
+ {{#form (extend this mixins='popover' hideValidationBox=true)}}
+ {{#if this.message}}
+ {{this.message}}
+ {{/if}}
+ {{>UI.contentBlock}}
+
+ {{#button action='cancel'
+ class=(concat 'btn btn-cancel ' (choose this.cancelClass 'btn-secondary'))
+ tagAttributes=(extend this.tagAttributes data-dismiss='modal')
+ }}{{choose this.cancelLabel 'Cancel'}}{{/button}}
+ {{#button action='confirm'
+ class=(concat 'btn btn-confirm ' (choose this.confirmClass 'btn-primary'))
+ }}{{choose this.confirmLabel 'Confirm'}}{{/button}}
+
+ {{/form}}
+
diff --git a/Packages/ohif-core/client/ui/index.js b/Packages/ohif-core/client/ui/index.js
index 6b3f69ab0..30d66293d 100644
--- a/Packages/ohif-core/client/ui/index.js
+++ b/Packages/ohif-core/client/ui/index.js
@@ -6,5 +6,6 @@ import './dialog/unsavedChangesDialog.js';
import './draggable/draggable.js';
import './dropdown/class.js';
import './dropdown/display.js';
+import './popover/display.js';
import './resizable/resizable.js';
import './unsavedChanges/unsavedChanges.js';
diff --git a/Packages/ohif-core/client/ui/popover/display.js b/Packages/ohif-core/client/ui/popover/display.js
new file mode 100644
index 000000000..0d1ff7ae6
--- /dev/null
+++ b/Packages/ohif-core/client/ui/popover/display.js
@@ -0,0 +1,82 @@
+import { Template } from 'meteor/templating';
+import { Blaze } from 'meteor/blaze';
+import { OHIF } from 'meteor/ohif:core';
+
+OHIF.ui.showPopover = (templateName, popoverData, options={}) => {
+ // Check if the given template exists
+ const template = Template[templateName];
+ if (!template) {
+ throw {
+ name: 'TEMPLATE_NOT_FOUND',
+ message: `Template ${templateName} not found.`
+ };
+ }
+
+ let promise;
+ let templateData;
+ if (popoverData && popoverData.promise instanceof Promise) {
+ // Use the given promise to control the modal
+ promise = popoverData.promise;
+ templateData = popoverData;
+ } else {
+ // Create a new promise to control the modal and store its resolve and reject callbacks
+ let promiseResolve;
+ let promiseReject;
+ promise = new Promise((resolve, reject) => {
+ promiseResolve = resolve;
+ promiseReject = reject;
+ });
+
+ // Render the dialog with the given template passing the promise object and callbacks
+ templateData = Object.assign({}, popoverData, {
+ promise,
+ promiseResolve,
+ promiseReject
+ });
+ }
+
+ const { element, event } = options;
+ const $element = $(element || event.currentTarget);
+
+ const defaults = {
+ content: '',
+ html: true,
+ trigger: 'manual',
+ placement: 'auto',
+ delay: {
+ show: 300,
+ hide: 300
+ }
+ };
+
+ const popoverOptions = Object.assign({} , defaults, options);
+ popoverOptions.content = Blaze.toHTMLWithData(template, popoverData);
+
+ $element.popover(popoverOptions);
+
+ $element.one('shown.bs.popover', function(event) {
+ const popoverId = $element.attr('aria-describedby');
+ const popover = document.getElementById(popoverId);
+ const $popover = $(popover);
+ const $popoverContent = $popover.find('.popover-content');
+ const dismissPopover = () => $element.popover('hide');
+
+ $popoverContent.html('');
+
+ const view = Blaze.renderWithData(template, templateData, $popoverContent[0]);
+ $element.one('hidden.bs.popover', () => {
+ Blaze.remove(view);
+ if (popoverOptions.trigger !== 'manual') {
+ $element.popover('destroy');
+ }
+ });
+
+ promise.then(dismissPopover).catch(dismissPopover);
+ });
+
+ if (popoverOptions.trigger === 'manual') {
+ $element.popover('show');
+ }
+
+ return promise;
+};
diff --git a/Packages/ohif-hotkeys/client/components/confirmReplacementPopover.html b/Packages/ohif-hotkeys/client/components/confirmReplacementPopover.html
new file mode 100644
index 000000000..81596896e
--- /dev/null
+++ b/Packages/ohif-hotkeys/client/components/confirmReplacementPopover.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/Packages/ohif-hotkeys/client/components/form.html b/Packages/ohif-hotkeys/client/components/form.html
index 439f73c94..72fc8ef89 100644
--- a/Packages/ohif-hotkeys/client/components/form.html
+++ b/Packages/ohif-hotkeys/client/components/form.html
@@ -13,27 +13,8 @@
{{/let}}
- {{#button class='btn btn-danger pull-left m-r-1' action='resetDefaults'}}Reset to Defaults{{/button}}
+ {{#button class='btn btn-danger pull-left' action='resetDefaults'}}Reset to Defaults{{/button}}
{{#button class='btn btn-primary pull-right' action='save'}}Save{{/button}}
{{/form}}
-
-
-
-
-
- | Function |
- Shortcut |
-
-
-
- {{#each input in this.inputs}}
-
- | {{input.label}} |
- {{>inputText (extend class='hotkey text-center' key=input.key value=input.value)}} |
-
- {{/each}}
-
-
-
diff --git a/Packages/ohif-hotkeys/client/components/form.js b/Packages/ohif-hotkeys/client/components/form.js
index 0aa8c4856..95bdde103 100644
--- a/Packages/ohif-hotkeys/client/components/form.js
+++ b/Packages/ohif-hotkeys/client/components/form.js
@@ -1,4 +1,3 @@
-import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { $ } from 'meteor/jquery';
import { _ } from 'meteor/underscore';
@@ -133,8 +132,8 @@ Template.hotkeysForm.helpers({
const right = list;
return {
- left,
- right
+ left,
+ right
};
}
});
diff --git a/Packages/ohif-hotkeys/client/components/formTable.html b/Packages/ohif-hotkeys/client/components/formTable.html
new file mode 100644
index 000000000..dba21cfc6
--- /dev/null
+++ b/Packages/ohif-hotkeys/client/components/formTable.html
@@ -0,0 +1,18 @@
+
+
+
+
+ | Function |
+ Shortcut |
+
+
+
+ {{#each input in this.inputs}}
+
+ | {{input.label}} |
+ {{>inputText (extend class='hotkey text-center' key=input.key value=input.value)}} |
+
+ {{/each}}
+
+
+
diff --git a/Packages/ohif-hotkeys/client/components/index.js b/Packages/ohif-hotkeys/client/components/index.js
index 67429ab28..133ed4591 100644
--- a/Packages/ohif-hotkeys/client/components/index.js
+++ b/Packages/ohif-hotkeys/client/components/index.js
@@ -1,2 +1,4 @@
+import './confirmReplacementPopover.html';
import './form.html';
import './form.js';
+import './formTable.html';
diff --git a/Packages/ohif-viewerbase/client/components/viewer/windowLevelPresets/form.html b/Packages/ohif-viewerbase/client/components/viewer/windowLevelPresets/form.html
index a97717eef..cbfdcf10e 100644
--- a/Packages/ohif-viewerbase/client/components/viewer/windowLevelPresets/form.html
+++ b/Packages/ohif-viewerbase/client/components/viewer/windowLevelPresets/form.html
@@ -23,7 +23,7 @@
- {{#button class='btn btn-danger pull-left m-r-1' action='resetDefaults'}}Reset to Defaults{{/button}}
+ {{#button class='btn btn-danger pull-left' action='resetDefaults'}}Reset to Defaults{{/button}}
{{#button class='btn btn-primary pull-right' action='save'}}Save{{/button}}
{{/form}}