Seperate Palette from the Diagram

Hello Team,
First of all, thank you Camunda team for this open source project, I’m working on integrating the bpmn-js in a web application, i would like to split modler by moving the palette tool in a standalone container separated from the diagram layout.
Could you please provide me the steps, code location or hints in order to perform this task.

kind regards,

Hi,

Think, most relevant place to start looking is this line.

One possible solutions would be to provide custom implementation of palette module, that overrides init method that attaches palette to a parent container.

Regarding styles, here is where relevant css starts.

Hope this helps.

Cheers,
Vladimir

1 Like

Thank you Vladimirs for your comments,

I have other questions from technical javascript prespective, According to my humble knowledge in bpmn js library and based on the provided link you are using require js for javascript file and module loading which is good practices and granted by running the applicatin througn browserify context.

in my case, i’m runing the web application using IIS Express web server and including the javascripts manually file e.g:

Example
<script src="http://www.w3schools.com/lib/w3data.js"></script>

Could you please provide me the way how to change the require loading by adding the src javascript file tag

Can you give the recommanded github repository to download that i can use to customize bpmn js by which i can use regular javascript inclusion,

Thanks and best regards,

Keep the good working.

1 Like

Hi,

Here is an example repository for building custom bundles for bpmn-js.

Cheers,
Vladimir

1 Like

kudos Vladmirs,
what about the way to use manual javascript inclusion instead of using require js:
Actually the provided example is based on loading modules thru require js so how to avoid use it in my context.

Thanks so much :slight_smile: for your time and effort.

Not sure what are your restrictions in terms of adding and replcaing new bundle/script.
Initial answer is still valid for your case, as overriding the module is done one initialisation faze (your custom code that that instantiates the modeler), no matter how you include/bundle your code.

Alternatively, you can build customized distribution of bpmn-js and replace original script with that one.

Cheers,
Vladimir

Just for clarification. We’re not using RequireJS for modules but Browserify. You may have mixed up those two. The keyword require doesn’t belong to RequireJS but to the CommonJS module syntax introduced by NodeJS and brought to the browser by Browserify. With Browserify you have to bundle your application before using it. Afterwards you can include a single bundled file in your project.

Hope that helps.

2 Likes

Thank Philipp,
As far as i understand, there is no need to include Browserfy or CommonJS in my project just include the bundled file generated by this command grunt browserify:bower (see this example).

Thank you again.

1 Like

Hello Guys,
What i understand require will call the modules only for server side (code running in node js),
How can i run the below without node js context in my case using Web Server for Chrome?

thank you.

var BpmnViewer = require('bpmn-js');

    var xml; // my BPMN 2.0 xml
    var viewer = new BpmnViewer({ container: 'body' });

    viewer.importXML(xml, function(err) {

      if (err) {
        console.log('error rendering', err);
      } else {
        console.log('rendered');
      }
    });

Hi,

Here is an example that does exactly that.

Cheers,
Vladimir

1 Like

Hi Vladimirs,
Is there any example to start with in order to override the init method and customize the palette container

thank you.

Hi,

I do not think so. Take a look in a few examples like this and this that show a few approaches on extending and modifying existing modules.

PR’s for complete examples are always welcome :slight_smile:.

Cheers,
Vladimir

Hi @dhaker:

I’ve just uploaded an example of what Vladimir was talking about. You can found it in the repository in the palette-override branch. Here is the diff, and the overridden palette is here.

Briefly, you have to create a custom palette provider (an example here and here) but overriding the original diagram-js/palette with your modified version.

Let me know if you have a doubt, I’ll try to help you as much as possible.

Regards,
David

1 Like

BTW @vladimirs.katusenoks,

I’d be glad of providing occasional examples to the repo. is this, right?

1 Like

Great!

Yes, that’s the right one :slight_smile:.

1 Like

Hello David,
Thank you for your dedication and collaboration, i will check your implmentation :slight_smile: ,
Luckily, I also come to the same solution by overriding the Palette.js file

I’m stepping with care but slowly to learn the the bpmn js library but i can do it with your help guys :slight_smile:
Thanks again David and bpmn team,

'use strict';

var inherits = require('inherits');

var isFunction = require('lodash/lang/isFunction'),
    forEach = require('lodash/collection/forEach');

var domify = require('min-dom/lib/domify'),
    domQuery = require('min-dom/lib/query'),
    domAttr = require('min-dom/lib/attr'),
    domClear = require('min-dom/lib/clear'),
    domClasses = require('min-dom/lib/classes'),
    domMatches = require('min-dom/lib/matches'),
    domDelegate = require('min-dom/lib/delegate'),
    domEvent = require('min-dom/lib/event');

var Palette = require('diagram-js/lib/features/palette/Palette');
var $ = require('jquery');

var toggleSelector = '.djs-palette-toggle',
    entrySelector = '.entry',
    elementSelector = toggleSelector + ', ' + entrySelector;

/**
 * A palette containing modeling elements.
 */
function DiagramPalette(eventBus, canvas, dragging) {

  
	Palette.call(this, eventBus, canvas, dragging);
  this._eventBus = eventBus;
  this._canvas = canvas;
  this._dragging = dragging;

  this._providers = [];

  var self = this;

  eventBus.on('tool-manager.update', function(event) {
    var tool = event.tool;

    self.updateToolHighlight(tool);
  });

  eventBus.on('i18n.changed', function() {
    self._update();
  });
}

inherits(DiagramPalette, Palette);
DiagramPalette.$inject = [ 'eventBus', 'canvas', 'dragging' ];
module.exports = DiagramPalette;

DiagramPalette.prototype._init = function() {
  var canvas = this._canvas,
      eventBus = this._eventBus;
 
  var parent =  document.querySelector("#palette"),
      container = this._container = domify(DiagramPalette.HTML_MARKUP),
      self = this;

	//$("djs-palette").removeClass(".djs-popup, .djs-palette");
  parent.appendChild(container);

  domDelegate.bind(container, elementSelector, 'click', function(event) {

    var target = event.delegateTarget;

    if (domMatches(target, toggleSelector)) {
      return self.toggle();
    }

    self.trigger('click', event);
  });

  // prevent drag propagation
  domEvent.bind(container, 'mousedown', function(event) {
    event.stopPropagation();
  });

  // prevent drag propagation
  domDelegate.bind(container, entrySelector, 'dragstart', function(event) {
    self.trigger('dragstart', event);
  });

  eventBus.fire('palette.create', {
    html: container
  });

  eventBus.on('canvas.resized', function() {
    if (parent.clientHeight < 650) {
      domClasses(container).add('two-column');
    } else {
      domClasses(container).remove('two-column');
    }
  });
};

/* markup definition */

DiagramPalette.HTML_MARKUP =
  '<div class="djs-palette">' +
    '<div class="djs-palette-entries"></div>' +
    '<div class="djs-palette-toggle"></div>' +
  '</div>';
1 Like

You’re welcome, Dhaker. I’m glad to hear you’re advancing on this :grin:. I consider it a very well structured library (you’ll find very few like this out there).

Regarding the code you posted, it’s basically the same that is here

Regards

1 Like

In date of today, is there a better (cleaner) solution to change the parent container of a Palette than overriding the entire class? How the canvas is passed to the Palette constructor?

Thank you.

Nevermind, I found how to do it. It’s a hack, but I find it cleaner than overriding an external library. Using the custom-elements-example, use this constructor instead:

function PaletteProvider(palette, create, elementFactory, spaceTool, lassoTool) {
  this._create = create;
  this._elementFactory = elementFactory;
  this._spaceTool = spaceTool;
  this._lassoTool = lassoTool;

  var parent =  document.querySelector("#palette")

  var originCanvasContainer = palette._canvas._container;
  palette._canvas._container = parent;
  palette._init();
  palette._canvas._container = originCanvasContainer;

  palette.registerProvider(this);
}

“pallete” refers to the parent class Palette (in diagram-js/lib/features/palette/Palette.js); the class generating a default palette with the good event bindings. “#palette” refers to the html container in .html file.

2 Likes

Hi,

I’ve also separated the palette from the diagram. But now I’ve the problem that when I drag an element from the palette into the canvas, that the canvas moves because I drag the element over the border of the canvas. I see that this scroll functionality (moving an element over the canvas border) is a great feature, but in my case it’s annoying. Is it possible to disable this scrolling or is there another workaround?

Best regards,
Christian