|
296 | 296 |
|
297 | 297 | var idSeq = 0; |
298 | 298 |
|
299 | | - var GridStackEngine = function(row, column, onchange, float, minRow, maxRow, items) { |
300 | | - this.row = row || 0; |
| 299 | + var GridStackEngine = function(column, onchange, float, maxRow, items) { |
301 | 300 | this.column = column || 12; |
302 | 301 | this.float = float || false; |
303 | | - this.minRow = minRow || 0; |
304 | | - this.maxRow = this.row ? this.row : maxRow || 0; |
| 302 | + this.maxRow = maxRow || 0; |
305 | 303 |
|
306 | 304 | this.nodes = items || []; |
307 | 305 | this.onchange = onchange || function() {}; |
|
344 | 342 | while (true) { |
345 | 343 | var collisionNode = this.nodes.find(Utils._collisionNodeCheck, {node: node, nn: nn}); |
346 | 344 | if (!collisionNode) { return; } |
347 | | - this.moveNode(collisionNode, collisionNode.x, node.y + node.height, |
| 345 | + var moved = this.moveNode(collisionNode, collisionNode.x, node.y + node.height, |
348 | 346 | collisionNode.width, collisionNode.height, true); |
| 347 | + if (!moved) { return; } // break inf loop if we couldn't move after all (ex: maxRow, fixed) |
349 | 348 | } |
350 | 349 | }; |
351 | 350 |
|
|
434 | 433 | if (Number.isNaN(node.width)) { node.width = defaults.width; } |
435 | 434 | if (Number.isNaN(node.height)) { node.height = defaults.height; } |
436 | 435 |
|
| 436 | + if (node.maxWidth !== undefined) { node.width = Math.min(node.width, node.maxWidth); } |
| 437 | + if (node.maxHeight !== undefined) { node.height = Math.min(node.height, node.maxHeight); } |
| 438 | + if (node.minWidth !== undefined) { node.width = Math.max(node.width, node.minWidth); } |
| 439 | + if (node.minHeight !== undefined) { node.height = Math.max(node.height, node.minHeight); } |
| 440 | + |
437 | 441 | if (node.width > this.column) { |
438 | 442 | node.width = this.column; |
439 | 443 | } else if (node.width < 1) { |
440 | 444 | node.width = 1; |
441 | 445 | } |
442 | | - |
443 | | - if (node.height < 1) { |
| 446 | + if (this.maxRow && node.height > this.maxRow) { |
| 447 | + node.height = this.maxRow; |
| 448 | + } else if (node.height < 1) { |
444 | 449 | node.height = 1; |
445 | 450 | } |
446 | 451 |
|
447 | 452 | if (node.x < 0) { |
448 | 453 | node.x = 0; |
449 | 454 | } |
| 455 | + if (node.y < 0) { |
| 456 | + node.y = 0; |
| 457 | + } |
450 | 458 |
|
451 | 459 | if (node.x + node.width > this.column) { |
452 | 460 | if (resizing) { |
|
455 | 463 | node.x = this.column - node.width; |
456 | 464 | } |
457 | 465 | } |
458 | | - |
459 | | - if (node.y < 0) { |
460 | | - node.y = 0; |
| 466 | + if (this.maxRow && node.y + node.height > this.maxRow) { |
| 467 | + if (resizing) { |
| 468 | + node.height = this.maxRow - node.y; |
| 469 | + } else { |
| 470 | + node.y = this.maxRow - node.height; |
| 471 | + } |
461 | 472 | } |
462 | 473 |
|
463 | 474 | return node; |
|
499 | 510 | GridStackEngine.prototype.addNode = function(node, triggerAddEvent) { |
500 | 511 | node = this._prepareNode(node); |
501 | 512 |
|
502 | | - if (node.maxWidth !== undefined) { node.width = Math.min(node.width, node.maxWidth); } |
503 | | - if (node.maxHeight !== undefined) { node.height = Math.min(node.height, node.maxHeight); } |
504 | | - if (node.minWidth !== undefined) { node.width = Math.max(node.width, node.minWidth); } |
505 | | - if (node.minHeight !== undefined) { node.height = Math.max(node.height, node.minHeight); } |
506 | | - |
507 | 513 | node._id = node._id || ++idSeq; |
508 | 514 |
|
509 | 515 | if (node.autoPosition) { |
|
560 | 566 | } |
561 | 567 | var hasLocked = Boolean(this.nodes.find(function(n) { return n.locked; })); |
562 | 568 |
|
563 | | - if (!this.maxRow && !this.row && !hasLocked) { |
| 569 | + if (!this.maxRow && !hasLocked) { |
564 | 570 | return true; |
565 | 571 | } |
566 | 572 |
|
567 | 573 | var clonedNode; |
568 | 574 | var clone = new GridStackEngine( |
569 | | - 0, |
570 | 575 | this.column, |
571 | 576 | null, |
572 | 577 | this.float, |
573 | 578 | 0, |
574 | | - 0, |
575 | 579 | this.nodes.map(function(n) { |
576 | 580 | if (n === node) { |
577 | 581 | clonedNode = $.extend({}, n); |
|
591 | 595 | return n !== clonedNode && Boolean(n.locked) && Boolean(n._dirty); |
592 | 596 | })); |
593 | 597 | } |
594 | | - if (this.maxRow || this.row) { |
| 598 | + if (this.maxRow) { |
595 | 599 | res &= clone.getRow() <= this.maxRow; |
596 | 600 | } |
597 | 601 |
|
598 | 602 | return res; |
599 | 603 | }; |
600 | 604 |
|
601 | 605 | GridStackEngine.prototype.canBePlacedWithRespectToHeight = function(node) { |
602 | | - if (!this.maxRow && !this.row) { |
| 606 | + if (!this.maxRow) { |
603 | 607 | return true; |
604 | 608 | } |
| 609 | + |
605 | 610 | var clone = new GridStackEngine( |
606 | | - 0, |
607 | 611 | this.column, |
608 | 612 | null, |
609 | 613 | this.float, |
610 | 614 | 0, |
611 | | - 0, |
612 | 615 | this.nodes.map(function(n) { return $.extend({}, n); })); |
613 | 616 | clone.addNode(node); |
614 | 617 | return clone.getRow() <= this.maxRow; |
|
637 | 640 | if (typeof width !== 'number') { width = node.width; } |
638 | 641 | if (typeof height !== 'number') { height = node.height; } |
639 | 642 |
|
640 | | - if (node.maxWidth !== undefined) { width = Math.min(width, node.maxWidth); } |
641 | | - if (node.maxHeight !== undefined) { height = Math.min(height, node.maxHeight); } |
642 | | - if (node.minWidth !== undefined) { width = Math.max(width, node.minWidth); } |
643 | | - if (node.minHeight !== undefined) { height = Math.max(height, node.minHeight); } |
644 | | - |
645 | | - if (node.x === x && node.y === y && node.width === width && node.height === height) { |
646 | | - return node; |
| 643 | + // constrain the passed in values and check if we're still changing our node |
| 644 | + var resizing = (node.width !== width || node.height !== height); |
| 645 | + var nn = { x: x, y: y, width: width, height: height, |
| 646 | + maxWidth: node.maxWidth, maxHeight: NodeIterator.maxHeight, minWidth: node.minWidth, minHeight: node.minHeight}; |
| 647 | + nn = this._prepareNode(nn, resizing); |
| 648 | + if (node.x === nn.x && node.y === nn.y && node.width === nn.width && node.height === nn.height) { |
| 649 | + return null; |
647 | 650 | } |
648 | 651 |
|
649 | | - var resizing = node.width !== width; |
650 | 652 | node._dirty = true; |
651 | 653 |
|
652 | | - node.x = x; |
653 | | - node.y = y; |
654 | | - node.width = width; |
655 | | - node.height = height; |
656 | | - |
657 | | - node.lastTriedX = x; |
658 | | - node.lastTriedY = y; |
659 | | - node.lastTriedWidth = width; |
660 | | - node.lastTriedHeight = height; |
661 | | - |
662 | | - node = this._prepareNode(node, resizing); |
| 654 | + node.x = node.lastTriedX = nn.x; |
| 655 | + node.y = node.lastTriedY = nn.y; |
| 656 | + node.width = node.lastTriedWidth = nn.width; |
| 657 | + node.height = node.lastTriedHeight = nn.height; |
663 | 658 |
|
664 | 659 | this._fixCollisions(node); |
665 | 660 | if (!noPack) { |
|
670 | 665 | }; |
671 | 666 |
|
672 | 667 | GridStackEngine.prototype.getRow = function() { |
673 | | - return this.row ? this.row : this.nodes.reduce(function(memo, n) { return Math.max(memo, n.y + n.height); }, 0); |
| 668 | + return this.nodes.reduce(function(memo, n) { return Math.max(memo, n.y + n.height); }, 0); |
674 | 669 | }; |
675 | 670 |
|
676 | 671 | GridStackEngine.prototype.beginUpdate = function(node) { |
|
716 | 711 | this.opts = Utils.defaults(opts, { |
717 | 712 | row: parseInt(this.$el.attr('data-gs-row')) || 0, |
718 | 713 | column: parseInt(this.$el.attr('data-gs-column')) || 12, |
719 | | - maxRow: parseInt(this.$el.attr('data-gs-row')) || 0 ? parseInt(this.$el.attr('data-gs-row')) : parseInt(this.$el.attr('data-gs-max-row')) || 0, |
720 | | - minRow: parseInt(this.$el.attr('data-gs-min-row')) || 0, |
| 714 | + minRow: opts.row || parseInt(this.$el.attr('data-gs-row')) ? opts.row || parseInt(this.$el.attr('data-gs-row')) : parseInt(this.$el.attr('data-gs-min-row')) || 0, |
| 715 | + maxRow: opts.row || parseInt(this.$el.attr('data-gs-row')) ? opts.row || parseInt(this.$el.attr('data-gs-row')) : parseInt(this.$el.attr('data-gs-max-row')) || 0, |
721 | 716 | itemClass: 'grid-stack-item', |
722 | 717 | placeholderClass: 'grid-stack-placeholder', |
723 | 718 | placeholderText: '', |
|
794 | 789 |
|
795 | 790 | this._initStyles(); |
796 | 791 |
|
797 | | - this.engine = new GridStackEngine(this.opts.row, this.opts.column, function(nodes, detachNode) { |
| 792 | + this.engine = new GridStackEngine(this.opts.column, function(nodes, detachNode) { |
798 | 793 | detachNode = (detachNode === undefined ? true : detachNode); |
799 | 794 | var maxHeight = 0; |
800 | 795 | this.nodes.forEach(function(n) { |
|
814 | 809 | } |
815 | 810 | }); |
816 | 811 | self._updateStyles(maxHeight + 10); |
817 | | - }, this.opts.float, this.opts.minRow, this.opts.maxRow); |
| 812 | + }, this.opts.float, this.opts.maxRow); |
818 | 813 |
|
819 | 814 | if (this.opts.auto) { |
820 | 815 | var elements = []; |
|
1162 | 1157 |
|
1163 | 1158 | GridStack.prototype._updateContainerHeight = function() { |
1164 | 1159 | if (this.engine._batchMode) { return; } |
1165 | | - var row = this.opts.minRow > this.engine.getRow() ? this.opts.minRow : this.engine.getRow(); |
| 1160 | + var row = this.engine.getRow(); |
| 1161 | + if (row < this.opts.minRow) { |
| 1162 | + row = this.opts.minRow; |
| 1163 | + } |
1166 | 1164 | // check for css min height. Each row is cellHeight + verticalMargin, until last one which has no margin below |
1167 | 1165 | var cssMinHeight = parseInt(this.$el.css('min-height')); |
1168 | 1166 | if (cssMinHeight > 0) { |
1169 | 1167 | var verticalMargin = this.opts.verticalMargin; |
1170 | | - var minRow = Math.round((cssMinHeight + verticalMargin) / (this.cellHeight() + verticalMargin)); |
| 1168 | + var minRow = Math.round((cssMinHeight + verticalMargin) / (this.cellHeight() + verticalMargin)); |
1171 | 1169 | if (row < minRow) { |
1172 | 1170 | row = minRow; |
1173 | 1171 | } |
|
1469 | 1467 | // Tempting to initialize the passed in opt with default and valid values, but this break knockout demos |
1470 | 1468 | // as the actual value are filled in when _prepareElement() calls el.attr('data-gs-xyz) before adding the node. |
1471 | 1469 | // opt = this.engine._prepareNode(opt); |
1472 | | - opt = opt || {}; |
1473 | 1470 | } else { |
1474 | 1471 | // old legacy way of calling with items spelled out - call us back with single object instead (so we can properly initialized values) |
1475 | 1472 | return this.addWidget(el, {x: opt, y: y, width: width, height: height, autoPosition: autoPosition, |
1476 | 1473 | minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, maxHeight: maxHeight, id: id}); |
1477 | 1474 | } |
1478 | 1475 |
|
1479 | 1476 | el = $(el); |
| 1477 | + if (opt) { // see knockout above |
| 1478 | + this.engine._prepareNode(opt); |
| 1479 | + } |
1480 | 1480 | this._writeAttr(el, opt); |
1481 | 1481 | this.$el.append(el); |
1482 | 1482 | return this.makeWidget(el); |
|
2030 | 2030 | * notifications (see doc for supported events) |
2031 | 2031 | */ |
2032 | 2032 | GridStack.prototype.on = function(eventName, callback) { |
| 2033 | + // check for array of names being passed instead |
| 2034 | + if (eventName.indexOf(' ') !== -1) { |
| 2035 | + var names = eventName.split(' '); |
| 2036 | + names.forEach(function(name) { this.on(name, callback) }, this); |
| 2037 | + return; |
| 2038 | + } |
| 2039 | + |
2033 | 2040 | if (eventName === 'change' || eventName === 'added' || eventName === 'removed') { |
2034 | 2041 | // native CustomEvent handlers - cash the generic handlers so we can remove |
2035 | 2042 | this._gsEventHandler = this._gsEventHandler || {}; |
|
2043 | 2050 |
|
2044 | 2051 | /** unsubscribe from the 'on' event */ |
2045 | 2052 | GridStack.prototype.off = function(eventName) { |
| 2053 | + // check for array of names being passed instead |
| 2054 | + if (eventName.indexOf(' ') !== -1) { |
| 2055 | + var names = eventName.split(' '); |
| 2056 | + names.forEach(function(name) { this.off(name, callback) }, this); |
| 2057 | + return; |
| 2058 | + } |
| 2059 | + |
2046 | 2060 | if (eventName === 'change' || eventName === 'added' || eventName === 'removed') { |
2047 | 2061 | // remove native CustomEvent handlers |
2048 | 2062 | if (this._gsEventHandler && this._gsEventHandler[eventName]) { |
|
0 commit comments