Creating header package and dropdown component
This commit is contained in:
parent
04e9a85def
commit
2d52c9ef0a
@ -97,6 +97,8 @@ ohif:log@0.0.1
|
|||||||
ohif:measurements@0.0.1
|
ohif:measurements@0.0.1
|
||||||
ohif:metadata@0.0.1
|
ohif:metadata@0.0.1
|
||||||
ohif:study-list@0.0.1
|
ohif:study-list@0.0.1
|
||||||
|
ohif:themes@0.0.1
|
||||||
|
ohif:themes-common@0.0.1
|
||||||
ohif:user-management@0.0.1
|
ohif:user-management@0.0.1
|
||||||
ohif:viewerbase@0.0.1
|
ohif:viewerbase@0.0.1
|
||||||
ohif:wadoproxy@0.0.1
|
ohif:wadoproxy@0.0.1
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import './mixins/action.js';
|
|||||||
import './mixins/button.js';
|
import './mixins/button.js';
|
||||||
import './mixins/checkbox.js';
|
import './mixins/checkbox.js';
|
||||||
import './mixins/component.js';
|
import './mixins/component.js';
|
||||||
|
import './mixins/dropdown.js';
|
||||||
import './mixins/form.js';
|
import './mixins/form.js';
|
||||||
import './mixins/formItem.js';
|
import './mixins/formItem.js';
|
||||||
import './mixins/group.js';
|
import './mixins/group.js';
|
||||||
|
|||||||
@ -76,6 +76,9 @@ class Mixin {
|
|||||||
static initData(data) {
|
static initData(data) {
|
||||||
// Split the mixins by space
|
// Split the mixins by space
|
||||||
const mixinsArray = data.mixins.split(' ');
|
const mixinsArray = data.mixins.split(' ');
|
||||||
|
|
||||||
|
// Control and ignore the mixins that have already been applied
|
||||||
|
const appliedOnData = [];
|
||||||
_.each(mixinsArray, mixinName => {
|
_.each(mixinsArray, mixinName => {
|
||||||
// Ignore blank strings
|
// Ignore blank strings
|
||||||
if (!mixinName) {
|
if (!mixinName) {
|
||||||
@ -86,7 +89,7 @@ class Mixin {
|
|||||||
const mixin = Mixin.getMixin(mixinName);
|
const mixin = Mixin.getMixin(mixinName);
|
||||||
|
|
||||||
// Initialize the data manipulation composition
|
// Initialize the data manipulation composition
|
||||||
mixin.init(null, data, [], ['onData']);
|
mixin.init(null, data, appliedOnData, ['onData']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +97,10 @@ class Mixin {
|
|||||||
static initAll(template, data) {
|
static initAll(template, data) {
|
||||||
// Split the mixins by space
|
// Split the mixins by space
|
||||||
const mixinsArray = data.mixins.split(' ');
|
const mixinsArray = data.mixins.split(' ');
|
||||||
|
|
||||||
|
// Control and ignore the mixins that have already been applied
|
||||||
|
const appliedCommon = [];
|
||||||
|
const appliedOnMixins = [];
|
||||||
_.each(mixinsArray, mixinName => {
|
_.each(mixinsArray, mixinName => {
|
||||||
// Ignore blank strings
|
// Ignore blank strings
|
||||||
if (!mixinName) {
|
if (!mixinName) {
|
||||||
@ -104,10 +111,10 @@ class Mixin {
|
|||||||
const mixin = Mixin.getMixin(mixinName);
|
const mixin = Mixin.getMixin(mixinName);
|
||||||
|
|
||||||
// Initialize blaze default compositions
|
// Initialize blaze default compositions
|
||||||
mixin.init(template, data, [], ['onCreated', 'onRendered', 'onDestroyed', 'events', 'helpers']);
|
mixin.init(template, data, appliedCommon, ['onCreated', 'onRendered', 'onDestroyed', 'events', 'helpers']);
|
||||||
|
|
||||||
// Execute some behaviors after all mixins are applied
|
// Execute some behaviors after all mixins are applied
|
||||||
mixin.init(template, data, [], ['onMixins']);
|
mixin.init(template, data, appliedOnMixins, ['onMixins']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { OHIF } from 'meteor/ohif:core';
|
|
||||||
import { Template } from 'meteor/templating';
|
import { Template } from 'meteor/templating';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* action: controls an element that will trigger some form API's method
|
* action: controls an element that will trigger some form API's method
|
||||||
@ -11,24 +11,32 @@ OHIF.mixins.action = new OHIF.Mixin({
|
|||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
const component = instance.component;
|
const component = instance.component;
|
||||||
|
|
||||||
|
// Add the form-action identification class
|
||||||
component.$element.addClass('form-action');
|
component.$element.addClass('form-action');
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click .form-action'(event, instance) {
|
'click .form-action'(event, instance) {
|
||||||
|
event.preventDefault();
|
||||||
const component = instance.component;
|
const component = instance.component;
|
||||||
|
|
||||||
// Extract the action and the params
|
// Extract action, params and disabled state
|
||||||
const { action, params } = instance.data;
|
const { action, params, disabled } = instance.data;
|
||||||
|
|
||||||
|
// Stop here if the component is disabled
|
||||||
|
if (disabled) return;
|
||||||
|
|
||||||
// Get the current component's API
|
// Get the current component's API
|
||||||
const api = component.getApi();
|
const api = component.getApi();
|
||||||
|
|
||||||
// Stop here if no API or action was defined
|
// Stop here calling the action if it's a function
|
||||||
if (!api || !action || typeof api[action] !== 'function') {
|
if (typeof action === 'function') {
|
||||||
return;
|
return action.call(this, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop here if no API or action was defined
|
||||||
|
if (!api || !action || typeof api[action] !== 'function') return;
|
||||||
|
|
||||||
// Call the defined action function
|
// Call the defined action function
|
||||||
api[action].call(this, params);
|
api[action].call(this, params);
|
||||||
}
|
}
|
||||||
|
|||||||
81
Packages/ohif-core/client/components/base/mixins/dropdown.js
Normal file
81
Packages/ohif-core/client/components/base/mixins/dropdown.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
import { Blaze } from 'meteor/blaze';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dropdown: controls a dropdown
|
||||||
|
*/
|
||||||
|
OHIF.mixins.dropdown = new OHIF.Mixin({
|
||||||
|
dependencies: 'form',
|
||||||
|
composition: {
|
||||||
|
onRendered() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
const { event, centered } = instance.data.options;
|
||||||
|
|
||||||
|
// Destroy the Blaze created view (either created with template calls or with renderWithData)
|
||||||
|
instance.destroyView = () => {
|
||||||
|
if (typeof instance.data.destroyView === 'function') {
|
||||||
|
instance.data.destroyView();
|
||||||
|
} else {
|
||||||
|
Blaze.remove(instance.view);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the dropdown element to enable position manipulation
|
||||||
|
const $dropdown = instance.$('.dropdown');
|
||||||
|
const dropdown = $dropdown[0];
|
||||||
|
const $dropdownMenu = $dropdown.children('.dropdown-menu');
|
||||||
|
|
||||||
|
dropdown.oncontextmenu = () => false;
|
||||||
|
|
||||||
|
const cssBefore = {
|
||||||
|
'z-index': 10000
|
||||||
|
};
|
||||||
|
if (event) {
|
||||||
|
cssBefore.position = 'fixed';
|
||||||
|
$dropdownMenu.bounded();
|
||||||
|
}
|
||||||
|
|
||||||
|
$dropdownMenu.css(cssBefore).focus();
|
||||||
|
|
||||||
|
// Postpone visibility change to allow CSS transitions
|
||||||
|
Meteor.defer(() => {
|
||||||
|
// Show the dropdown
|
||||||
|
$dropdown.addClass('open');
|
||||||
|
|
||||||
|
// Change the dropdown position if mouse event was given
|
||||||
|
if (event) {
|
||||||
|
const position = {
|
||||||
|
left: event.clientX,
|
||||||
|
top: event.clientY
|
||||||
|
};
|
||||||
|
|
||||||
|
if (centered) {
|
||||||
|
position.left -= $dropdownMenu.outerWidth() / 2;
|
||||||
|
position.top -= $dropdownMenu.outerHeight() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dropdownMenu.css(position).trigger('spatialChanged');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click .form-action.disabled'(event, instance) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
},
|
||||||
|
|
||||||
|
'click .dropdown'(event, instance) {
|
||||||
|
const $target = $(event.target);
|
||||||
|
if ($target.hasClass('disabled')) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
} else {
|
||||||
|
instance.destroyView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { OHIF } from 'meteor/ohif:core';
|
|
||||||
import { Template } from 'meteor/templating';
|
import { Template } from 'meteor/templating';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* link: controls a link
|
* link: controls a link
|
||||||
|
|||||||
@ -1,8 +1,29 @@
|
|||||||
<template name="dropdownForm">
|
<template name="dropdownForm">
|
||||||
{{#form class='dropdown' api=this.api hideValidationBox=true}}
|
{{#form (extend this mixins='dropdown' class='dropdown' hideValidationBox=true)}}
|
||||||
{{>dropdownBackdrop}}
|
{{>dropdownBackdrop}}
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu {{this.options.menuClasses}}">
|
||||||
{{>UI.contentBlock}}
|
{{#if UI.contentBlock}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{else}}
|
||||||
|
{{#each item in this.items}}
|
||||||
|
{{#if item.separatorBefore}}
|
||||||
|
<li role="separator" class="divider"></li>
|
||||||
|
{{/if}}
|
||||||
|
<li class="{{#if item.disabled}}disabled{{/if}}">
|
||||||
|
{{#link item}}
|
||||||
|
{{#if item.iconClasses}}
|
||||||
|
<i class="{{item.iconClasses}}"></i>
|
||||||
|
{{/if}}
|
||||||
|
{{#if item.text}}
|
||||||
|
<span>{{item.text}}</span>
|
||||||
|
{{/if}}
|
||||||
|
{{/link}}
|
||||||
|
</li>
|
||||||
|
{{#if item.separatorAfter}}
|
||||||
|
<li role="separator" class="divider"></li>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
</ul>
|
</ul>
|
||||||
{{/form}}
|
{{/form}}
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -1,34 +0,0 @@
|
|||||||
import { Template } from 'meteor/templating';
|
|
||||||
import { Blaze } from 'meteor/blaze';
|
|
||||||
import { $ } from 'meteor/jquery';
|
|
||||||
import { _ } from 'meteor/underscore';
|
|
||||||
|
|
||||||
Template.dropdownForm.onRendered(() => {
|
|
||||||
const instance = Template.instance();
|
|
||||||
const dropdown = instance.$('.dropdown');
|
|
||||||
|
|
||||||
// Show the dropdown
|
|
||||||
dropdown.addClass('open');
|
|
||||||
dropdown.find('ul.dropdown-menu li a').addClass('noselect');
|
|
||||||
|
|
||||||
// Destroy the Blaze created view (either created with template calls or with renderWithData)
|
|
||||||
instance.destroyView = () => {
|
|
||||||
if (_.isFunction(instance.data.destroyView)) {
|
|
||||||
instance.data.destroyView();
|
|
||||||
} else {
|
|
||||||
Blaze.remove(instance.view);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
Template.dropdownForm.events({
|
|
||||||
'click .dropdown'(event, instance) {
|
|
||||||
let target = $(event.target);
|
|
||||||
if (target.hasClass('disabled')) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
} else {
|
|
||||||
instance.destroyView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@ -17,7 +17,6 @@ import './dialog/unsavedChangesDialog.js';
|
|||||||
|
|
||||||
import './dropdown/backdrop.html';
|
import './dropdown/backdrop.html';
|
||||||
import './dropdown/form.html';
|
import './dropdown/form.html';
|
||||||
import './dropdown/form.js';
|
|
||||||
|
|
||||||
import './form/button.html';
|
import './form/button.html';
|
||||||
import './form/form.html';
|
import './form/form.html';
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { $ } from 'meteor/jquery';
|
||||||
|
import { _ } from 'meteor/underscore';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
// Allow attaching to jQuery selectors
|
// Allow attaching to jQuery selectors
|
||||||
@ -61,6 +63,19 @@ class Bounded {
|
|||||||
// Add the bounded class to the element
|
// Add the bounded class to the element
|
||||||
this.$element.addClass('bounded');
|
this.$element.addClass('bounded');
|
||||||
|
|
||||||
|
// Handle the positioning on window resize
|
||||||
|
const $window = $(window);
|
||||||
|
const windowResizeHandler = () => {
|
||||||
|
// Check if the element is still in DOM and remove the handler if it is not
|
||||||
|
if (!this.$element.closest(document.documentElement).length) {
|
||||||
|
$window.off('resize', windowResizeHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$element.trigger('spatialChanged');
|
||||||
|
};
|
||||||
|
|
||||||
|
$window.on('resize', windowResizeHandler);
|
||||||
|
|
||||||
// Trigger the bounding check for the first timepoint
|
// Trigger the bounding check for the first timepoint
|
||||||
setTimeout(() => this.$element.trigger('spatialChanged'));
|
setTimeout(() => this.$element.trigger('spatialChanged'));
|
||||||
}
|
}
|
||||||
|
|||||||
29
Packages/ohif-core/client/ui/dropdown/dropdown.js
Normal file
29
Packages/ohif-core/client/ui/dropdown/dropdown.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
import { Blaze } from 'meteor/blaze';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
OHIF.ui.showDropdown = (items=[], options={}) => {
|
||||||
|
// Prepare the method to destroy the view
|
||||||
|
let view;
|
||||||
|
const destroyView = () => Blaze.remove(view);
|
||||||
|
const templateData = {
|
||||||
|
items,
|
||||||
|
options,
|
||||||
|
destroyView
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render the dialog with the given template and data
|
||||||
|
const parentElement = options.parentElement || document.body;
|
||||||
|
view = Blaze.renderWithData(Template.dropdownForm, templateData, parentElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
Meteor.startup(() => {
|
||||||
|
OHIF.ui.showDropdown([{
|
||||||
|
text: 'test 1',
|
||||||
|
action: () => console.warn('test1Clicked'),
|
||||||
|
separatorAfter: true
|
||||||
|
}, {
|
||||||
|
text: 'test 2',
|
||||||
|
action: () => console.warn('test2Clicked')
|
||||||
|
}]);
|
||||||
|
});
|
||||||
@ -4,6 +4,7 @@ import './dialog/display.js';
|
|||||||
import './dialog/spatial.js';
|
import './dialog/spatial.js';
|
||||||
import './dialog/unsavedChangesDialog.js';
|
import './dialog/unsavedChangesDialog.js';
|
||||||
import './draggable/draggable.js';
|
import './draggable/draggable.js';
|
||||||
|
import './dropdown/dropdown.js';
|
||||||
import './dropdown/form.js';
|
import './dropdown/form.js';
|
||||||
import './resizable/resizable.js';
|
import './resizable/resizable.js';
|
||||||
import './unsavedChanges/unsavedChanges.js';
|
import './unsavedChanges/unsavedChanges.js';
|
||||||
|
|||||||
12
Packages/ohif-header/components/header.html
Normal file
12
Packages/ohif-header/components/header.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<template name="header">
|
||||||
|
<div class="header noselect {{headerClasses}}">
|
||||||
|
<div class="clearfix">
|
||||||
|
<a target='_blank' class="brand pull-left" href="{{choose this.brandHref '/'}}">
|
||||||
|
{{>section 'brand'}}
|
||||||
|
</a>
|
||||||
|
<div class="header-menu pull-right">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
31
Packages/ohif-header/components/header.styl
Normal file
31
Packages/ohif-header/components/header.styl
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
$expandedHeight = 160px
|
||||||
|
|
||||||
|
.header
|
||||||
|
height: $topBarHeight
|
||||||
|
padding: 10px 10px 0
|
||||||
|
theme('color', '$textPrimaryColor')
|
||||||
|
theme('background-color', '$primaryBackgroundColor')
|
||||||
|
transition(all 0.5s ease)
|
||||||
|
|
||||||
|
&>.clearfix
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
.brand
|
||||||
|
background-image: url(/packages/pim_webviewer/assets/logo.svg)
|
||||||
|
background-repeat: no-repeat
|
||||||
|
background-size: 100%
|
||||||
|
display: block
|
||||||
|
font-size: 9px
|
||||||
|
height: 3.5em
|
||||||
|
text-decoration: none
|
||||||
|
width: 34.6em
|
||||||
|
|
||||||
|
&.studyList
|
||||||
|
background-color: rgba(21, 25, 30, 0.7)
|
||||||
|
height: $expandedHeight
|
||||||
|
padding-left: $studyListPadding
|
||||||
|
padding-right: $studyListPadding
|
||||||
|
|
||||||
|
.brand
|
||||||
|
font-size: 16px
|
||||||
|
margin-top: 44px
|
||||||
2
Packages/ohif-header/index.js
Normal file
2
Packages/ohif-header/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import './components/header.html';
|
||||||
|
import './components/header.styl';
|
||||||
19
Packages/ohif-header/package.js
Normal file
19
Packages/ohif-header/package.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Package.describe({
|
||||||
|
name: 'ohif:header',
|
||||||
|
summary: 'OHIF Header Templates',
|
||||||
|
version: '0.0.1'
|
||||||
|
});
|
||||||
|
|
||||||
|
Package.onUse(function(api) {
|
||||||
|
api.versionsFrom('1.4.2.3');
|
||||||
|
|
||||||
|
// Meteor packages
|
||||||
|
api.use('ecmascript');
|
||||||
|
api.use('stylus');
|
||||||
|
|
||||||
|
// OHIF dependencies
|
||||||
|
api.use('ohif:core', 'client');
|
||||||
|
|
||||||
|
// Client imports
|
||||||
|
api.addFiles('index.js', 'client');
|
||||||
|
});
|
||||||
@ -9,7 +9,7 @@ Package.onUse(function(api) {
|
|||||||
|
|
||||||
api.use('stylus');
|
api.use('stylus');
|
||||||
|
|
||||||
api.use('ohif:themes-common');
|
api.use('ohif:themes-common', 'client');
|
||||||
|
|
||||||
// Importable themes related variables
|
// Importable themes related variables
|
||||||
api.addFiles('themes.styl', 'client', { isImport: true });
|
api.addFiles('themes.styl', 'client', { isImport: true });
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user