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