all files / block-manager/plugins/block/ block-renderer.js

99.55% Statements 223/224
91.67% Branches 110/120
100% Functions 29/29
99.55% Lines 222/223
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379   1390× 1390× 1390× 1390×   1390× 1390×   1390× 1390×   1390× 1390× 1390× 1390× 1390× 1390× 1390× 1390× 1390× 1390×   7053×             7053× 7053× 7053× 18×   7053× 290×     6763×   7053×   22× 22× 22× 22×   332× 309×     23×     6763× 6763× 6763×   5412× 5412×   167× 167×       563× 563×   85× 85×   61× 61×   336× 336×   120× 120× 120×   18× 18×     6763× 6763× 6763×     6763× 6763× 563× 563× 563×     6200× 6115×     290× 290× 132×   158× 158×   290× 290×     1022×   1021× 1021×   1020× 1020×   1019× 1019×   1396× 1396×   1395× 2988× 2988× 2988× 2471×   2988× 420×   2988× 258× 382× 27×         1395× 1395× 1395× 3095× 50×           7053×     7114× 7114× 61×     2990×     2989×     19× 19× 19× 19× 19× 19×   1613× 1613×   332× 332×   332×   332× 158× 158× 158×           332× 332× 332× 332× 312×     20×   332× 60×   332× 332×             332× 164×   332×     148× 148×       148× 64×   148×     38× 38× 38× 38× 38× 51×   38× 38× 77× 51×                         38× 38×     137× 137× 137× 137× 137× 104×             104× 30×     137×     61× 61×   18× 18× 18× 18× 18×             18×     18×     19× 19×       19× 19×   860× 860× 860× 860× 839×                 860× 753×   860×       38×       38×       1390× 1390× 1390× 1390× 1390× 1390× 1390× 1390× 1390× 1390× 1390×        
define(["require", "exports", "@syncfusion/ej2-base", "../../../models/enums", "../../../common/utils/block", "../../renderer/blocks/index", "../../../common/utils/selection", "../../../common/constant", "../../../common/constant", "../../renderer/content/content-renderer"], function (require, exports, ej2_base_1, enums_1, block_1, index_1, selection_1, constant_1, constants, content_renderer_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var BlockRenderer = (function () {
        function BlockRenderer(manager) {
            this.parent = manager;
            this.contentRenderer = new content_renderer_1.ContentRenderer(this.parent);
            this.initializeRenderers();
            this.addEventListeners();
        }
        BlockRenderer.prototype.addEventListeners = function () {
            this.parent.observer.on('modelChanged', this.handleBlockUIUpdates, this);
            this.parent.observer.on(constant_1.events.destroy, this.destroy, this);
        };
        BlockRenderer.prototype.removeEventListeners = function () {
            this.parent.observer.off('modelChanged', this.handleBlockUIUpdates);
            this.parent.observer.off(constant_1.events.destroy, this.destroy);
        };
        BlockRenderer.prototype.initializeRenderers = function () {
            this.paragraphRenderer = new index_1.ParagraphRenderer(this.parent);
            this.headingRenderer = new index_1.HeadingRenderer(this.parent);
            this.listRenderer = new index_1.ListRenderer(this.parent);
            this.quoteRenderer = new index_1.QuoteRenderer(this.parent);
            this.codeRenderer = new index_1.CodeRenderer(this.parent);
            this.imageRenderer = new index_1.ImageRenderer(this.parent);
            this.calloutRenderer = new index_1.CalloutRenderer(this.parent);
            this.collapsibleRenderer = new index_1.CollapsibleRenderer(this.parent);
            this.commonBlocksRenderer = new index_1.CommonBlocksRenderer(this.parent);
            this.tableRenderer = new index_1.TableRenderer(this.parent);
        };
        BlockRenderer.prototype.createBlockElement = function (block) {
            var blockElement = ej2_base_1.createElement('div', {
                id: block.id,
                className: "e-block " + (block_1.isListTypeBlock(block.blockType) ? 'e-list-block' : '') + (block.cssClass ? ' ' + block.cssClass : ''),
                attrs: {
                    'data-block-type': block.blockType
                }
            });
            this.updateBlockCssClass(blockElement, block.cssClass);
            this.updateBlockIndentAttribute(blockElement, block.indent);
            if (block.blockType === enums_1.BlockType.Divider) {
                blockElement.setAttribute('contenteditable', 'false');
            }
            if (block_1.isChildrenTypeBlock(block.blockType)) {
                this.renderNestedTypeBlockContent(block, blockElement);
            }
            else {
                this.renderBlockContent(block, blockElement);
            }
            return blockElement;
        };
        BlockRenderer.prototype.createAndReplaceBlockElement = function (currentBlockId, newBlockId) {
            var newBlockElement = this.createBlockElement(block_1.getBlockModelById(newBlockId, this.parent.getEditorBlocks()));
            var currentElement = this.parent.getBlockElementById(currentBlockId);
            currentElement.replaceWith(newBlockElement);
            return this.parent.getBlockElementById(newBlockId);
        };
        BlockRenderer.prototype.insertBlockElementInDOM = function (blockElement, targetElement, isAfter) {
            if (targetElement) {
                targetElement.insertAdjacentElement(isAfter ? 'afterend' : 'beforebegin', blockElement);
            }
            else {
                this.parent.blockContainer.appendChild(blockElement);
            }
        };
        BlockRenderer.prototype.renderBlockContent = function (block, blockElement) {
            blockElement.setAttribute('data-block-type', block.blockType);
            var contentElement;
            switch (block.blockType) {
                case enums_1.BlockType.Paragraph:
                    contentElement = this.paragraphRenderer.renderParagraph(block);
                    break;
                case enums_1.BlockType.Heading:
                    contentElement = this.headingRenderer.renderHeading(block);
                    break;
                case enums_1.BlockType.BulletList:
                case enums_1.BlockType.NumberedList:
                case enums_1.BlockType.Checklist:
                    contentElement = this.listRenderer.renderListItem(block, blockElement);
                    break;
                case enums_1.BlockType.Code:
                    contentElement = this.codeRenderer.renderCodeBlock(block);
                    break;
                case enums_1.BlockType.Image:
                    contentElement = this.imageRenderer.renderImage(block);
                    break;
                case enums_1.BlockType.Table:
                    contentElement = this.tableRenderer.renderTable(block, blockElement);
                    break;
                case enums_1.BlockType.Quote:
                    contentElement = this.quoteRenderer.renderQuote(block);
                    blockElement.classList.add('e-quote-block');
                    break;
                case enums_1.BlockType.Divider:
                    contentElement = this.commonBlocksRenderer.renderDivider(blockElement);
                    break;
                case enums_1.BlockType.Template:
                    contentElement = this.commonBlocksRenderer.renderTemplateBlock(block, blockElement);
                    break;
            }
            Eif (contentElement) {
                this.populateClassListsForContent(block, contentElement);
                blockElement.appendChild(contentElement);
            }
        };
        BlockRenderer.prototype.populateClassListsForContent = function (block, contentElement) {
            var notAllowedTypes = [enums_1.BlockType.Code, enums_1.BlockType.Callout];
            if (block_1.isListTypeBlock(block.blockType)) {
                var listItem = contentElement.querySelector('li');
                Eif (listItem) {
                    listItem.classList.add('e-block-content');
                }
            }
            else if (notAllowedTypes.indexOf(block.blockType) === -1) {
                contentElement.classList.add('e-block-content');
            }
        };
        BlockRenderer.prototype.renderNestedTypeBlockContent = function (block, blockElement) {
            var contentElement;
            if (block.blockType === enums_1.BlockType.Callout) {
                contentElement = this.calloutRenderer.renderCallout(block, blockElement);
            }
            else Eif (block.blockType.toString().startsWith('Collapsible')) {
                contentElement = this.collapsibleRenderer.renderCollapsibleBlock(block, blockElement);
            }
            Eif (contentElement) {
                blockElement.appendChild(contentElement);
            }
        };
        BlockRenderer.prototype.reRenderBlockContent = function (block) {
            if (!block) {
                return;
            }
            var blockElement = this.parent.getBlockElementById(block.id);
            if (!blockElement) {
                return;
            }
            var contentElement = block_1.getBlockContentElement(blockElement);
            if (!contentElement) {
                return;
            }
            contentElement.innerHTML = '';
            this.contentRenderer.renderContent(block, contentElement);
        };
        BlockRenderer.prototype.renderBlocks = function (blocks) {
            var _this = this;
            if (blocks.length <= 0) {
                return;
            }
            blocks.forEach(function (block) {
                var blockElement = _this.createBlockElement(block);
                _this.insertBlockIntoDOM(blockElement);
                if (!block_1.isAlwaysOnPlaceHolderBlk(block.blockType)) {
                    _this.parent.togglePlaceholder(blockElement, false);
                }
                if (block_1.isListTypeBlock(block.blockType)) {
                    _this.parent.listPlugin.updateListItemMarkers(blockElement);
                }
                if (block_1.isChildrenTypeBlock(block.blockType) && block.properties.children.length > 0) {
                    block.properties.children.forEach(function (childBlock) {
                        if (block_1.isListTypeBlock(childBlock.blockType)) {
                            _this.parent.listPlugin.updateListItemMarkers(blockElement.querySelector('#' + childBlock.id));
                        }
                    });
                }
            });
            requestAnimationFrame(function () {
                Eif (_this.parent) {
                    blocks.forEach(function (block) {
                        if (block.blockType === enums_1.BlockType.Checklist && _this.listRenderer) {
                            _this.listRenderer.toggleCheckedState(block, block.properties.isChecked, true);
                        }
                    });
                }
            });
        };
        BlockRenderer.prototype.updateBlockCssClass = function (blockElement, customClass) {
            if (customClass) {
                ej2_base_1.addClass([blockElement], customClass.trim().split(' '));
            }
        };
        BlockRenderer.prototype.updateBlockIndentAttribute = function (blockElement, indentValue) {
            blockElement.style.setProperty(constants.INDENT_KEY, (indentValue * 20).toString());
            if (this.parent.rootEditorElement.contains(blockElement)) {
                this.parent.floatingIconAction.showFloatingIcons(blockElement);
            }
        };
        BlockRenderer.prototype.insertBlockIntoDOM = function (blockElement, afterElement) {
            if (afterElement) {
                this.parent.blockContainer.insertBefore(blockElement, afterElement.nextSibling);
            }
            else {
                this.parent.blockContainer.appendChild(blockElement);
            }
        };
        BlockRenderer.prototype.clearEditorAndRenderDefaultBlock = function () {
            this.parent.blockContainer.innerHTML = '';
            var blockElement = this.createBlockElement(this.parent.getEditorBlocks()[0]);
            this.parent.blockContainer.appendChild(blockElement);
            this.parent.setFocusToBlock(blockElement);
            selection_1.setCursorPosition(block_1.getBlockContentElement(blockElement), 0);
            this.parent.floatingIconAction.showFloatingIcons(blockElement);
        };
        BlockRenderer.prototype.handleBlockUIUpdates = function (options) {
            var _this = this;
            switch (options.type) {
                case 'AddBlock': {
                    var _a = options.state, addedBlock = _a.addedBlock, targetBlockModel = _a.targetBlockModel, preventUIUpdate = _a.preventUIUpdate, isAfter = _a.isAfter, preventEventTrigger = _a.preventEventTrigger, preventUpdateAction = _a.preventUpdateAction, forceIgnoreTargetUpdate = _a.forceIgnoreTargetUpdate;
                    var isIgnoredTypes = [enums_1.BlockType.Callout, enums_1.BlockType.CollapsibleHeading, enums_1.BlockType.CollapsibleParagraph,
                        enums_1.BlockType.Divider, enums_1.BlockType.Image];
                    var isIgnored = forceIgnoreTargetUpdate ||
                        (targetBlockModel && isIgnoredTypes.indexOf(targetBlockModel.blockType) !== -1);
                    if (!isIgnored && targetBlockModel) {
                        this.reRenderBlockContent(targetBlockModel);
                        Eif (!preventUpdateAction) {
                            this.parent.eventService.addChange({
                                action: 'Update',
                                data: { block: targetBlockModel }
                            });
                        }
                    }
                    var blockElement = this.createBlockElement(addedBlock);
                    var targetElement = targetBlockModel ? this.parent.getBlockElementById(targetBlockModel.id) : null;
                    this.insertBlockElementInDOM(blockElement, targetElement, isAfter);
                    if (!preventUIUpdate) {
                        this.parent.setFocusAndUIForNewBlock(blockElement);
                    }
                    else {
                        this.parent.togglePlaceholder(blockElement, false);
                    }
                    if (block_1.isListTypeBlock(addedBlock.blockType)) {
                        this.parent.listPlugin.recalculateMarkersForListItems();
                    }
                    this.parent.adjustViewForFocusedBlock();
                    this.parent.eventService.addChange({
                        action: 'Insertion',
                        data: {
                            block: addedBlock,
                            targetId: targetBlockModel ? targetBlockModel.id : ''
                        }
                    });
                    if (!preventEventTrigger) {
                        this.parent.observer.notify('triggerBlockChange', this.parent.eventService.getChanges());
                    }
                    break;
                }
                case 'DeleteBlock': {
                    ej2_base_1.detach(options.state.blockElement);
                    this.parent.eventService.addChange({
                        action: 'Deletion',
                        data: { block: options.state.removedBlock }
                    });
                    if (!options.state.preventEventTrigger) {
                        this.parent.observer.notify('triggerBlockChange', this.parent.eventService.getChanges());
                    }
                    break;
                }
                case 'MoveBlock': {
                    var _b = options.state, destination = _b.destination, fromElements = _b.fromElements, isMovingUp_1 = _b.isMovingUp, toBlockDOM_1 = _b.toBlockDOM, movedBlocks = _b.movedBlocks;
                    var allBlocks = Array.from(this.parent.blockContainer.children);
                    var parentElement_1 = this.getParentElementToInsert(destination, allBlocks);
                    var targetToInsert_1 = (isMovingUp_1 ? toBlockDOM_1 : toBlockDOM_1.nextSibling);
                    fromElements.forEach(function (el) {
                        parentElement_1.insertBefore(el, targetToInsert_1);
                    });
                    var reversedFromModels_1 = movedBlocks.slice().reverse();
                    movedBlocks.forEach(function (data) {
                        var prevParent = reversedFromModels_1.find(function (fromModel) { return fromModel.parent !== null; });
                        _this.parent.eventService.addChange({
                            action: 'Moved',
                            data: {
                                block: data.model,
                                targetId: toBlockDOM_1.id,
                                isMovingUp: isMovingUp_1,
                                prevParent: prevParent ? prevParent.model : undefined,
                                currentParent: options.state.destination.toParentBlockModel
                                    ? options.state.destination.toParentBlockModel
                                    : undefined
                            }
                        });
                    });
                    this.parent.observer.notify('triggerBlockChange', this.parent.eventService.getChanges());
                    break;
                }
                case 'TransformBlock': {
                    var _c = options.state, block = _c.block, shouldPreventUpdates = _c.shouldPreventUpdates, oldBlockClone = _c.oldBlockClone, preventEventTrigger = _c.preventEventTrigger;
                    var blockElement = this.parent.getBlockElementById(block.id);
                    var newBlockElement = this.createBlockElement(block);
                    blockElement.replaceWith(newBlockElement);
                    if (!shouldPreventUpdates) {
                        this.parent.eventService.addChange({
                            action: 'Update',
                            data: {
                                block: block,
                                prevBlock: oldBlockClone
                            }
                        });
                        if (!preventEventTrigger) {
                            this.parent.observer.notify('triggerBlockChange', this.parent.eventService.getChanges());
                        }
                    }
                    break;
                }
                case 'IndentBlock':
                    this.updateBlockIndentAttribute(this.parent.getBlockElementById(options.state.blockId), options.state.newIndent);
                    break;
                case 'ReplaceBlock': {
                    var _d = options.state, block = _d.block, oldBlock = _d.oldBlock, targetBlockId = _d.targetBlockId, preventEventTrigger = _d.preventEventTrigger;
                    var blockElement = this.parent.getBlockElementById(targetBlockId);
                    var newBlockElement = this.createBlockElement(block);
                    blockElement.replaceWith(newBlockElement);
                    this.parent.eventService.addChange({
                        action: 'Update',
                        data: {
                            block: block,
                            prevBlock: oldBlock
                        }
                    });
                    Iif (!preventEventTrigger) {
                        this.parent.observer.notify('triggerBlockChange', this.parent.eventService.getChanges());
                    }
                    break;
                }
                case 'DefaultEmptyBlock':
                    this.clearEditorAndRenderDefaultBlock();
                    this.parent.eventService.addChange({
                        action: 'Insertion',
                        data: { block: this.parent.getEditorBlocks()[0] }
                    });
                    this.parent.observer.notify('triggerBlockChange', this.parent.eventService.getChanges());
                    break;
                case 'ReRenderBlockContent': {
                    var data = options.state.data;
                    data.forEach(function (data) {
                        _this.reRenderBlockContent(data.block);
                        if (!options.state.preventChangesTracking) {
                            _this.parent.eventService.addChange({
                                action: 'Update',
                                data: {
                                    block: data.block,
                                    prevBlock: data.oldBlock
                                }
                            });
                        }
                    });
                    if (!options.state.preventEventTrigger) {
                        this.parent.observer.notify('triggerBlockChange', this.parent.eventService.getChanges());
                    }
                    break;
                }
            }
        };
        BlockRenderer.prototype.getParentElementToInsert = function (destination, allBlocks) {
            var wrapperClassName = destination.toParentBlockModel
                ? (destination.toParentBlockModel.blockType === enums_1.BlockType.Callout ? '.' + constants.CALLOUT_CONTENT_CLS :
                    destination.toParentBlockModel.blockType.toString().startsWith('Collapsible') ? '.' + constants.TOGGLE_CONTENT_CLS : '')
                : '';
            return wrapperClassName
                ? allBlocks[destination.toParentBlockIndex].querySelector(wrapperClassName)
                : this.parent.blockContainer;
        };
        BlockRenderer.prototype.destroy = function () {
            this.removeEventListeners();
            this.contentRenderer = null;
            this.paragraphRenderer = null;
            this.headingRenderer = null;
            this.listRenderer = null;
            this.codeRenderer = null;
            this.quoteRenderer = null;
            this.calloutRenderer = null;
            this.collapsibleRenderer = null;
            this.commonBlocksRenderer = null;
            this.tableRenderer = null;
        };
        return BlockRenderer;
    }());
    exports.BlockRenderer = BlockRenderer;
});