123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- class Dashboard {
- //@TODO:
- // - Pouvoir indiquer que la dashboard à une taille dynamique :
- // - On laisse toujours 2-3 lignes de placeholder sous le dernier widget
- // - On recalcule le nb de lignes de placeholder en plus à afficher sous le dernier widget à chaque add / resize / move / delete d'un widget
- constructor(options) {
- this.options = $.extend({
- columnNumber : 1,
- lineNumber : 1,
- placeHolderPadding : 10
- },options);
- this.widgets = {};
- var grid = '<div class="dashboard-grid">';
- for(var u=0 ; u<options.lineNumber;u++){
- for(var i=0 ; i<options.columnNumber;i++){
- grid += '<div data-row="'+u+'" data-column="'+i+'" style="grid-area: '+(u+1)+" / "+(i+1)+" / "+(u+1)+" / "+(i+1)+';" class="dashboard-placeholder"><i class="fa fa-plus placeholder-add"></i></div>';
- }
- }
- grid += '</div>';
- this.grid = $(grid);
- this.options.element.addClass('dashboard-container');
- this.options.element.css({width:'100%',height:'100%'});
- this.options.element.append(this.grid);
- this.widgetTemplate = $('#dashboard-widget-template').html();
- this.placeHolders = $('.dashboard-placeholder');
- this.placeHolders.initialWidth = this.placeHolders.eq(0).outerWidth();
- this.placeHolders.initialHeight = this.placeHolders.eq(0).outerHeight();
- this.placeHolders.render = function(placeholder, offsets, delay){
- var delay = delay!=null ? delay : 200;
- var offsets = $.extend({
- rowStart: 0,
- rowEnd: 0,
- columnStart: 0,
- columnEnd: 0
- }, offsets);
- var rowStart = parseInt(placeholder.attr('data-row'))+1+parseInt(offsets.rowStart);
- var rowEnd = parseInt(placeholder.attr('data-row'))+1+parseInt(offsets.rowEnd);
- var columnStart = parseInt(placeholder.attr('data-column'))+1+parseInt(offsets.columnStart);
- var columnEnd = parseInt(placeholder.attr('data-column'))+1+parseInt(offsets.columnEnd);
- setTimeout(function(){
- placeholder.css({
- 'grid-row': rowStart+'/'+rowEnd,
- 'grid-column': columnStart+'/'+columnEnd,
- });
- }, delay);
- }
- this.triggers = [];
- var object = this;
- this.placeHolders.droppable({
- tolerance: 'pointer',
- classes: { "ui-droppable-hover": 'drag-over' },
- over: function(event, ui){
- //@TODO:
- // - Gérer les overflow de la grid => ex: lacher un widget en bas de gris doit recalculer le placeholder le plus bas possible sans sortir du cadre
- // - Ne pas pouvoir superposer des widgets
- var currentWidget = ui.draggable;
- var offsets = {
- rowEnd: currentWidget.attr('data-height'),
- columnEnd: currentWidget.attr('data-width')
- }
- //On custom la grid du placeholder avec la taille du widget
- object.placeHolders.render($(this), offsets, 0);
- },
- out: function(event, ui){
- //On reset la grid du placeholder
- object.placeHolders.render($(this));
- },
- drop: function(event, ui) {
- var placeholder = $(this);
- //On reset la grid du placeholder
- object.placeHolders.render(placeholder);
- var data = placeholder.data();
- var widgetId = ui.draggable.attr('data-id');
- object.widgets[widgetId].column = data.column;
- object.widgets[widgetId].row = data.row;
- object.renderPositions();
- object.trigger('move', object.widgetToArray(object.widgets[widgetId]));
- }
- });
- $(window).resize(function() {
- object.renderPositions();
- });
- $(window).mousemove(function(e){
- if(!object.resizing) return;
- $('.dashboard-widget').css('z-index', '');
- object.resizing.element.css('z-index', 1000);
- var objectPosition = object.resizing.element.position();
- object.resizing.element.css('width',(e.clientX - objectPosition.left)+'px');
- object.resizing.element.css('height',(e.clientY - objectPosition.top - 50)+'px');
- //On affiche la taille finale du widget avec de la couleur sur les placeholders pour guider le resize
- object.placeHolders.removeClass('drag-over');
- var width = Math.round(object.resizing.element.outerWidth() / object.placeHolders.initialWidth);
- var height = Math.round(object.resizing.element.outerHeight() / object.placeHolders.initialHeight);
- var resizePlaceholder = [];
- for(var i=parseInt(object.resizing.column); i<parseInt(parseInt(object.resizing.column)+width); i++){
- for(var j=parseInt(object.resizing.row); j<parseInt(parseInt(object.resizing.row)+height); j++){
- resizePlaceholder.push($('.dashboard-placeholder[data-row="'+j+'"][data-column="'+i+'"]').get(0));
- }
- }
- $(resizePlaceholder).addClass('drag-over')
- });
- $(window).mouseup(function(){
- if(!object.resizing) return;
- object.placeHolders.removeClass('drag-over bordered');
- var width = Math.round(object.resizing.element.outerWidth() / object.placeHolders.initialWidth);
- var height = Math.round(object.resizing.element.outerHeight() / object.placeHolders.initialHeight);
- object.widgets[object.resizing.id].width = width;
- object.widgets[object.resizing.id].height = height;
- object.widgets[object.resizing.id].element.attr({
- 'data-width': width,
- 'data-height': height,
- })
- object.renderPositions();
- object.trigger('resize', object.widgetToArray(object.widgets[object.resizing.id]));
- object.resizing = null;
- });
- $('.dashboard-placeholder').click(function(){
- var placeholder = $(this);
- object.trigger('placeholder-click',{
- element : placeholder,
- row: placeholder.attr('data-row'),
- column: placeholder.attr('data-column')
- });
- });
- }
- on(event,callback){
- if(!this.triggers[event]) this.triggers[event] = [];
- this.triggers[event].push(callback);
- return this;
- }
- trigger(event,data){
- if(!this.triggers[event]) return;
- if(!data) data = {};
- var abort = false;
- for(var k in this.triggers[event]){
- if(this.triggers[event][k](data) === true) abort = true;
- }
- return abort;
- }
- //Ajoute un ou plusieurs widgets
- addWidgets(widgets){
- var object = this;
- for(var k in widgets){
- var widgetOptions = $.extend({
- id: Math.floor(Math.random() * 100) + Date.now(),
- draggable: true,
- resizeable: true,
- removable: true,
- width: 1,
- height: 1,
- row: 0,
- column:0,
- options: [],
- label: 'Sans titre',
- content: "Aucun contenu"
- }, widgets[k]);
- widgetOptions.options.push({
- icon: 'fas fa-ellipsis-v',
- class: 'widget-option-configure',
- label: 'Configurer',
- click: function(element){
- object.configureWidget($(element).closest('.dashboard-widget').attr('data-id'));
- }
- });
- widgetOptions.options.push({
- icon: 'fa fa-times',
- class: 'widget-option-delete',
- label: 'Supprimer',
- click: function(element){
- object.deleteWidget($(element).closest('.dashboard-widget').attr('data-id'));
- }
- });
- object.addWidget(widgetOptions)
- }
- //Gestion de la disposition des widgets sur la dashboard
- this.renderPositions();
- }
- //Ajout d'un widget en fonction de paramètre
- addWidget(widgetOptions){
- var object = this;
- //Ajout du widget au tableau de widgets interne
- object.widgets[widgetOptions.id] = widgetOptions;
- //Render de la template pour les propriétés du widget courant
- object.renderContent(widgetOptions.id);
- var widgetElement = $(object.widgets[widgetOptions.id].element);
- object.grid.append(widgetElement);
- widgetElement.draggable({
- handle: '.widget-header-title',
- containment: object.grid,
- "ui-draggable-dragging" : "widget-dragging",
- start: function(event){
- var element = $(event.currentTarget);
- if(!element.hasClass('widget-draggable')) return false;
- $('.dashboard-widget').css('z-index','');
- element.css('z-index',1000);
- }
- });
- widgetElement.find('.dashboard-widget-resize').mousedown(function(){
- var element = $(this).closest('.dashboard-widget');
- if(!element.hasClass('widget-resizeable'))return;
- object.resizing = object.widgets[element.attr('data-id')];
- $('.dashboard-placeholder').addClass('bordered');
- });
- object.trigger('add', object.widgetToArray(widgetOptions));
- }
- //Supprime un widget en fonction de son id
- deleteWidget(id){
- var widget = this.widgets[id];
- if(this.trigger('delete',this.widgetToArray(widget))) return;
- this.widgets[id].element.remove();
- }
- configureWidget(id){
- $('#dashboard-modal').modal('show');
- this.trigger('configure', id);
- }
- widgetToArray(widget){
- if(!widget) return {};
- return {
- id: widget.id,
- draggable: widget.draggable,
- resizeable: widget.resizeable,
- removable: widget.removable,
- width: widget.width,
- height: widget.height,
- row: widget.row,
- column: widget.column,
- label: widget.label,
- content: widget.content,
- icon: widget.icon,
- headerBackground: widget.headerBackground
- };
- }
- //Render d'un widget en fonction de ses paramètres
- //Gère le refresh du widget si l'élément est déjà existant
- renderContent(id) {
- var widget = this.widgets[id];
- var widgetElement = widget.element!=null ? widget.element : $(Mustache.render(this.widgetTemplate, widget));
- if(widget.label !== null) widgetElement.find('.widget-header-title').html(widget.label);
- if(widget.icon !== null) widgetElement.find('.widget-header-icon i').attr('class', widget.icon);
- if(widget.headerBackground !== null) widgetElement.find('.dashboard-widget-header').css('backgroundColor',widget.headerBackground);
- if(widget.options !== null){
- var tpl = '<li class="{{class}}" title="{{label}}"><i class="{{icon}}"></i></li>';
- widgetElement.find('.widget-header-options').html('');
- for(var u in widget.options){
- var option = $(Mustache.render(tpl, widget.options[u]));
- if(widget.options[u].click){
- option.data('click',widget.options[u].click);
- option.click(function(){
- $(this).data('click')(this);
- });
- }
- widgetElement.find('.widget-header-options').append(option);
- }
- }
- widgetElement
- .toggleClass('widget-draggable', widget.draggable)
- .toggleClass('widget-resizeable', widget.resizeable)
- .toggleClass('widget-removable', widget.removable);
- if(widget.content !== null) widgetElement.find('.dashboard-widget-content').html(widget.content);
- widget.element = widgetElement;
- }
- //Rafraichit le contenu des widgets en fonction du tableau de widgets interne
- renderContents() {
- for(var k in this.widgets){
- var widget = this.widgets[k];
- this.renderContent(widget.id);
- }
- }
- //Resize / Replace les widgets en fonction de la taille de la fenetre et des cellules de grilles
- renderPositions(){
- var placeholderWidth = this.placeHolders.initialWidth;
- var placeholderHeight = this.placeHolders.initialHeight;
- for(var k in this.widgets){
- var widget = this.widgets[k];
- var cell = $('[data-row="'+widget.row+'"][data-column="'+widget.column+'"]').position();
- if(!cell) continue;
- widget.element.css({
- width: ((widget.width * placeholderWidth)-(this.options.placeHolderPadding*2))+'px',
- height: ((widget.height * placeholderHeight)-(this.options.placeHolderPadding*2))+'px',
- top: (cell.top+this.options.placeHolderPadding)+'px',
- left: (cell.left+this.options.placeHolderPadding)+'px'
- });
- }
- }
- }
|