feat(Viewer): allow dynamic attach / detach from DOM

Closes #655

BREAKING CHANGE:

* Viewer / Modeler do not attach to `body` anymore per
  default. Use `new Viewer({ container: 'body' })` to
  restore the old behavior.
This commit is contained in:
Christian Kaps 2017-01-27 10:09:34 +01:00 committed by Nico Rehwaldt
parent decd23360a
commit 6dc4af5396
6 changed files with 129 additions and 61 deletions

View File

@ -119,9 +119,11 @@ module.exports = function(grunt) {
grunt.registerTask('test', [ 'karma:single' ]);
grunt.registerTask('lint', [ 'eslint:check' ]);
grunt.registerTask('auto-test', [ 'karma:unit' ]);
grunt.registerTask('build', [ 'bundle', 'copy' ]);
grunt.registerTask('default', [ 'eslint:check', 'test', 'build' ]);
grunt.registerTask('default', [ 'lint', 'test', 'build' ]);
};

View File

@ -32,6 +32,19 @@ viewer.importXML(xml, function(err) {
});
```
### Dynamic Attach/Detach
You may attach or detach the viewer dynamically to any element on the page, too:
```javascript
var viewer = new BpmnViewer();
// attach it to some element
viewer.attachTo('#container');
// detach the panel
viewer.detach();
```
## Installation

View File

@ -8,7 +8,6 @@
var assign = require('lodash/object/assign'),
omit = require('lodash/object/omit'),
isString = require('lodash/lang/isString'),
isNumber = require('lodash/lang/isNumber');
var domify = require('min-dom/lib/domify'),
@ -46,8 +45,7 @@ function checkValidationError(err) {
var DEFAULT_OPTIONS = {
width: '100%',
height: '100%',
position: 'relative',
container: 'body'
position: 'relative'
};
@ -356,9 +354,49 @@ Viewer.prototype.off = function(event, callback) {
this.get('eventBus').off(event, callback);
};
Viewer.prototype.attachTo = function(parentNode) {
if (!parentNode) {
throw new Error('parentNode required');
}
// ensure we detach from the
// previous, old parent
this.detach();
// unwrap jQuery if provided
if (parentNode.get) {
parentNode = parentNode.get(0);
}
if (typeof parentNode === 'string') {
parentNode = domQuery(parentNode);
}
var container = this._container;
parentNode.appendChild(container);
this._emit('attach', {});
};
Viewer.prototype.detach = function() {
var container = this._container,
parentNode = container.parentNode;
if (!parentNode) {
return;
}
this._emit('detach', {});
parentNode.removeChild(container);
};
Viewer.prototype._init = function(container, moddle, options) {
this._container = container;
var baseModules = options.modules || this.getModules(),
additionalModules = options.additionalModules || [],
staticModules = [
@ -377,6 +415,10 @@ Viewer.prototype._init = function(container, moddle, options) {
// invoke diagram constructor
Diagram.call(this, diagramOptions);
if (options && options.container) {
this.attachTo(options.container);
}
};
/**
@ -393,21 +435,7 @@ Viewer.prototype._emit = function(type, event) {
Viewer.prototype._createContainer = function(options) {
var parent = options.container,
container;
// support jquery element
// unwrap it if passed
if (parent.get) {
parent = parent.get(0);
}
// support selector
if (isString(parent)) {
parent = domQuery(parent);
}
container = domify('<div class="bjs-container"></div>');
var container = domify('<div class="bjs-container"></div>');
assign(container.style, {
width: ensureUnit(options.width),
@ -415,8 +443,6 @@ Viewer.prototype._createContainer = function(options) {
position: options.position
});
parent.appendChild(container);
return container;
};

View File

@ -6,7 +6,8 @@
"all": "grunt",
"dev": "grunt auto-test",
"distro": "grunt build",
"test": "grunt test"
"test": "grunt test",
"lint": "grunt lint"
},
"repository": {
"type": "git",

View File

@ -94,25 +94,6 @@ describe('Modeler', function() {
});
describe('defaults', function() {
it('should use <body> as default parent', function(done) {
var xml = require('../fixtures/bpmn/simple.bpmn');
var modeler = new Modeler();
modeler.importXML(xml, function(err, warnings) {
expect(modeler.container.parentNode).to.equal(document.body);
done(err, warnings);
});
});
});
describe('translate support', function() {
var xml = require('../fixtures/bpmn/simple.bpmn');

View File

@ -72,25 +72,6 @@ describe('Viewer', function() {
});
describe('defaults', function() {
it('should use <body> as default parent', function(done) {
var xml = require('../fixtures/bpmn/simple.bpmn');
var viewer = new Viewer();
viewer.importXML(xml, function(err, warnings) {
expect(viewer.container.parentNode).to.equal(document.body);
done(err, warnings);
});
});
});
describe('overlay support', function() {
it('should allow to add overlays', function(done) {
@ -753,6 +734,33 @@ describe('Viewer', function() {
});
it('should attach the viewer to the given parent', function(done) {
var xml = require('../fixtures/bpmn/simple.bpmn');
var viewer = new Viewer({ container: container });
viewer.importXML(xml, function(err, warnings) {
expect(viewer.container.parentNode).to.equal(container);
done(err, warnings);
});
});
it('should not attach the viewer automatically if no parent was given', function(done) {
var xml = require('../fixtures/bpmn/simple.bpmn');
var viewer = new Viewer();
viewer.importXML(xml, function(err, warnings) {
expect(viewer.container.parentNode).to.equal(null);
done(err, warnings);
});
});
});
@ -929,4 +937,41 @@ describe('Viewer', function() {
});
describe('#attachTo', function() {
it('should attach the viewer', function(done) {
var xml = require('../fixtures/bpmn/simple.bpmn');
var viewer = new Viewer();
viewer.importXML(xml, function(err, warnings) {
expect(viewer.container.parentNode).to.equal(null);
viewer.attachTo(container);
expect(viewer.container.parentNode).to.equal(container);
done(err, warnings);
});
});
});
describe('#detach', function() {
it('should detach the viewer', function(done) {
var xml = require('../fixtures/bpmn/simple.bpmn');
var viewer = new Viewer({ container: container });
viewer.importXML(xml, function(err, warnings) {
expect(viewer.container.parentNode).to.equal(container);
viewer.detach();
expect(viewer.container.parentNode).to.equal(null);
done(err, warnings);
});
});
});
});