joint+handsontable实现两张电子表格连线关联代码

代码语言:html

所属分类:图表

代码描述:joint+handsontable实现两张电子表格连线关联代码

代码标签: joint handsontable 两张 电子 表格 连线 关联 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  

  
<link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/joint.3.7.2.css">
<link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/handsontable.full.min.css">
<style>
#paper {
  position: absolute;
  right: 0;
  top: 0;
  left: 0;
  bottom: 0;
  overflow: hidden;
}

#logo {
  position: absolute;
  bottom: 25px;
  right: 25px;
}

.joint-highlighted {
  stroke: #5a87f7;
  stroke-width: 3;
}
.joint-highlighted.label rect {
  fill: #e9effe;
  stroke: #5a87f7;
}
.joint-highlighted.label text {
  stroke: none;
}

.handsontable .table-header {
  background: #fcfdc4;
}
</style>

  
</head>

<body translate="no">
  <div id="paper"></div>

  <link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/rappid.3.7.3.css">

<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/lodash.4.17.21.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/backbone-min.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/joint.3.7.2.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/handsontable.full.js"></script>
      <script >
const {
    dia,
    shapes,
    highlighters,
    util,
    linkTools,
} = joint;

const HotModel = dia.Element.define('HotModel', {
    size: {
        width: 300,
        height: 0
    },
    z: 1,
    data: null,
    ports: {
        groups: {
            top: {
                z: 0,
                position: {
                    name: 'line',
                    args: {
                        start: {
                            x: 50,
                            y: -15
                        },
                        end: {
                            x: 'calc(w)',
                            y: -15
                        }
                    }
                },
                markup: util.svg/*xml*/`
                      <line @selector="portLine" x1="0" y1="0" x2="0" y2="30" stroke="#131e29" stroke-width="2"/>
                      <rect @selector="portBody" magnet="true" x="-5" y="-5" width="10" height="10" stroke="#131e29" stroke-width="2" fill="white" />
                  `
            }
        }
    }
});

const HotFlags = {
    // RenderView is used to render the adaptive card inside the foreign object
    RenderView: '@render-view',
    // UpdateView is used to update the size of the foreign object
    // and the color of border
    UpdateView: '@update-view',
    // TransformView is used to position and rotate the view
    TransformView: '@transform-view',
    // MeasureView is used to measure the view and update
    // the size of the model
    MeasureView: '@measure-view'
};

const HotModelView = dia.ElementView.extend({

    // The root of the element view is the <g> element by default.
    tagName: 'g',

    HEADER_HEIGHT: 30,
    COL_WIDTH: 50,

    // Whenever the model attributes change (the map key is the attribute name),
    // the update() method will be called, which will contain all the flags that were reported.
    presentationAttributes: {
        size: [HotFlags.UpdateView],
        position: [HotFlags.TransformView],
        angle: [HotFlags.TransformView],
        label: [HotFlags.RenderView],
    },

    // The initFlag property is a list of flags that will be reported to the paper
    // when the element view is initialized.
    initFlag: [HotFlags.RenderView, HotFlags.UpdateView, HotFlags.TransformView, HotFlags.MeasureView],

    confirmUpdate: function(flags) {
        if (this.hasFlag(flags, HotFlags.RenderView)) this.render();
        if (this.hasFlag(flags, HotFlags.UpdateView)) this.update();
        // `updateTransformation` is the original method of the `dia.ElementView`
        // it applies the `transform` attribute to the root element i.e. the `<foreignObject>`
        if (this.hasFlag(flags, HotFlags.TransformView)) this.updateTransformation();
        if (this.hasFlag(flags, HotFlags.MeasureView)) this.resizeModel();
    },

    init: function() {
        this.el.setAttribute('magnet', 'false');
        // Create a ResizeObserver to measure the card's size
        this.resizeObserver = new ResizeObserver(() => this.requestMeasurement());
    },

    onRemove() {
        this.releaseResources();
    },

    releaseResources() {
        const {
            hot,
            resizeObserver
        } = this;
        if (!hot) return;
        hot.destroy();
        resizeObserver.disconnect();
        this.hot = null;
        this.selectors = null;
    },

    render: function() {
        const {
            resizeObserver,
            HEADER_HEIGHT
        } = this;

        this.releaseResources();

        const markup =  util.svg/*xml*/`
            <rect @selector="header" height="${HEADER_HEIGHT}" fill="#F0F0F0" stroke="#DEDEDE"/>
            <rect @selector="border" height="3" fill="#131e239" stroke-width="1"/>
            <text @selector="label"
                y="${HEADER_HEIGHT / 2}"
                fill="#131e29"
                dominant-baseline="central"
                text-anchor="middle"
                font-size="14"
                font-family="sans-serif"
                font-weight="bold"
            />
            <foreignObject @selector="fo" y="${HEADER_HEIGHT}">
                <div xmlns="http://www.w3.org/1999/xhtml" @selector="container"></div>
            </foreignObject>
        `;

        const view = this;
        const docs = this.parseDOMJSON(markup);
        this.selectors = docs.selectors;
        this.el.appendChild(docs.fragment);

        const hot = new Handsontable(this.selectors.container, {
            data: this.model.get('data'),
            cells: (row, col) => {
                return {
                    readOnly: row === 0,
                    className: row === 0 ? 'table-header' : ''
                };
            },
            colHeaders: true,
            rowHeaders: true,
            height: 'auto',
            selectionMode: 'multiple',
            licenseKey: 'non-commercial-and-evaluation', // for non-commercial use only
            contextMenu: {
                items: {
                    row_below: {
                        name: 'Add row'
                    },
                    remove_row: {
                        disabled() {
                            if (this.getSelectedLast()[0] < 1) return true;
                            return this.countRows() < 2;
                        }
                    },
                    sp1: '---------',
                    calculate: {
                        name: 'Calculate column',
                        disabled() {
                            const [row, col] = this.getSelectedLast();
                            return row !== -1 || col === 0;
                        },
                        callback() {
                            const col = this.getSelectedLast()[1];
                            const data = this.getDataAtCol(col);
                            data.forEach((value, index) => {
                                calcValue(view, index, col, value);
                            });
                        }
                    },
                }
            }
        });

        // Keep a reference to the AdaptiveCard instance
        this.hot = hot;

        this.addHooks();
        this.addEventListeners();

        // Observe the table's size changes
        resizeObserver.observe(hot.rootElement);

        this._renderPorts();
    },

    addHooks: function() {

        const {
            hot
        } = this;
        if (!hot) return;

        hot.addHook('afterChange', (changes, type) => {
            this.notify('element:change', changes, type);
            this.requestMeasurement();
        });

        hot.addHook('beforeOnCellMouseDown', (event, coords, element) => {
            this.constructor.activeView = this;
        });

        hot.addHook('afterSelection', () => {
            if (this.constructor.activeView !== this) {
                return;
            }
            const selection = [];
            this.hot.getSelectedRange().forEach((range) => {
                const [min, max] = [range.from.col, range.to.col].sort();
                for (let i = Math.max(0, min); i <= max; i++) {
                    selection.push(`col-${i}`);
                }
            });

            this.notify('element:columns:selection', util.uniq(selection).sort());
        });

        hot.addHook('afterDeselect', () => {
            if (this.constructor.activeView !== this) return;
            this.notify('element:columns:selection', []);
        });
    },

    addEventListeners: function() {
        this.listenTo(paper, 'element:columns:selection', (elementView, selection) => {
            if (elementView === this) return;
            this.hot.deselectCell();
        });
    },

    requestMeasurement(opt = {}) {
        this.requestUpdate(this.getFlag(HotFlags.MeasureView), opt);
    },

    resizeModel() {
        const {
            model,
            hot,
            HEADER_HEIGHT,
            COL_WIDTH,
        } = this;
        if (!hot) return;

        const {
            width,
            height
        } = model.size();

        // add +1 because the foreign object is shifted by 1px
        const hotHeight = hot.rootElement.offsetHeight + HEADER_HEIGHT + 1;
        const countCols = hot.countCols();
        // add +1 to prevent the horizontal scrollbar to appear
        let hotWidth = 1;
        for (let i = 0; i <= countCols; i++) {
            hotWidth += hot.getColWidth(i);
        }

        if (height === hotHeight && width === hotWidth) return;

        model.resize(hotWidth, hotHeight, {
            view: this.cid
        });

        const ports = [];
        let x = COL_WIDTH;
        for (let i = 0; i < countCols; i++) {
            const colWidth = hot.getColWidth(i);
            ports.push({
                id: `col-${i}`,
                group: 'top',
                args: {
                    x: x + co.........完整代码请登录后点击上方下载按钮下载查看

网友评论0