import $ from './util/dom-core.js'; import {getParentByClassname, getParentNodeByClass, isEmptyElement, trim} from './util/util.js'; import QuestionTools from './util/question'; import JQuery from 'jquery'; let yzPage = function (manage, $page) { this.manage = manage; this.editor = manage.editor; this.pageIndex = this.manage.pageIndex; this.id = ('lsiten_editor_page_'+Math.random()).replace('.','_') + this.pageIndex; this.$textElem = $('
'); this.$colums = []; this.paragraphIndex = 0; // 已经初始化后的内容 this.$page = $page; this.lineHeight = 25; this._init(); manage.$el.append(this.$textElem); } yzPage.prototype = { constructor: yzPage, _init: function () { this._initStyles(); this._initColumn(); this._initPositionPlaceholder(); this._initPAndNPlaceholder(); this.questionTools = new QuestionTools(); }, /** * function 初始化样式 */ _initStyles: function () { this.$textElem.css('position', 'relative') .css('outline', 'none') .css('word-wrap', 'break-word') .css('font-size', '14px') .css('-webkit-line-break', 'after-white-space') .css('height', this._pagesHeight[this.editor.pageSize]) }, /** * function 初始化栏 */ _initColumn: function () { let colums = this.editor.columnNumber; let height = this._pagesHeight[this.editor.pageSize]; let widthColumn = 100 / colums + '%'; // 初始化栏数据 let $columnData = []; if (this.$page) { $columnData = this.$page.find('.js-column'); } for (let i = 0; i < colums; i++) { let $columItem = null; if ($columnData[i]) { $columItem = $($columnData[i]); } else { $columItem = $(''); $columItem.attr('data-column-i', i); $columItem.attr('data-column-page', this.pageIndex); // $columItem.attr('contenteditable', true); $columItem.css('height', height); $columItem.css('position', 'relative'); $columItem.css('overflow', 'hidden'); $columItem.css('float', 'left'); $columItem.css('width', widthColumn); } this.$colums.push($columItem); this.$textElem.append($columItem); } this.currentColumn = 0; }, /** * function 添加表头 */ addHeader: function () { this.editor.cmd.do('answerHeader', this); }, /** * function 添加段落 */ addParagraph: function () { let $column = this.$colums[this.currentColumn]; let $paragraph = $(''); $paragraph.css('margin', 0) .css('padding', '0 25px') .css('outline', 'none') .css('box-sizing', 'border-box') .css('white-space', 'pre-wrap') .css('line-height', '1.75') .css('text-align', 'left'); let index = this.pageIndex + '-' + this.paragraphIndex++; $paragraph.attr('data-index', index); let $currentParagraph = this.manage.editorPosition.currentParagraph; if (!$currentParagraph && !$column[0].childNodes.length) { $column.append($paragraph); } else { if (this.manage.editorPosition.currentParagraph !== this.$el) { $column.append($paragraph); } else { $paragraph.insertAfter($currentParagraph); } } return $paragraph; }, // 更新头部 updateHeader: function () { }, _placeholderTemplate: function () { let $postionDom = $(''); $postionDom.css('background-color', '#000'); $postionDom.css('position', 'absolute'); $postionDom.attr('contenteditable', false); $postionDom.html(''); $postionDom.css('width', '25px'); $postionDom.css('height', '16px'); return $postionDom; }, /** * function 生成正反面定位符 */ _initPAndNPlaceholder: function () { let count = this.pageIndex + 2; for (let i = 0; i < count; i++) { let template = this._placeholderTemplate(); let top = i * 22 - 16; template.css('width', '25px').css('height', '16px').css('left', '-25px').css('top', top + 'px'); this.$textElem.append(template); } }, /** * function 初始化占位符 */ _initPositionPlaceholder: function () { let $columns = this.$colums; let clength = $columns.length; let cwidth = this._pagesWidth[this.editor.pageSize] / clength; let lastIndex = clength - 1; for (let i = 0; i < clength; i++) { let $template = this._placeholderTemplate(); let $templateb = this._placeholderTemplate(); let left = i * cwidth - 25; if (i > 0) { left += 15 $template.css('left', left + 'px').css('top', '-16px'); this.$textElem.append($template); } $templateb.css('left', left + 'px').css('bottom', '-16px'); this.$textElem.append($templateb); if (i === lastIndex) { let $template1 = this._placeholderTemplate(); let $template1b = this._placeholderTemplate(); $template1.css('right', '-25px').css('top', '-16px'); $template1b.css('right', '-25px').css('bottom', '-16px'); this.$textElem.append($template1); this.$textElem.append($template1b); } } }, /** * function 更新跨栏符 */ _updateCrossColumn: function ($column) { let index =parseInt($column.attr('data-column-i')); if (index === 0) { return ''; } let column = $column[0]; let firstParagh = column.firstChild; firstParagh = this._cycleFindParagraph(firstParagh); if (firstParagh) { let page = column.parentNode; if (page) { let $page = $(page); let columnIndex = parseInt(column.getAttribute('data-column-i')); let crossPlaceholder = '.js-cross-placeholder-' + columnIndex; let classname = 'js-cross-placeholder-' + columnIndex; let $placeholder = $page.find(crossPlaceholder); let firstBorder = firstParagh.firstChild; if (firstParagh.className && firstParagh.className.indexOf('js-split-paragraph') > -1) { if (firstBorder && firstBorder.className && firstBorder.className.indexOf('js-lsiten-border') > -1) { if (!$placeholder.length) { // 添加跨栏符 // 判断是否有该栏跨栏符 let $template = this._placeholderTemplate(); let cwidth = this._pagesWidth[this.editor.pageSize] / parseInt(this.editor.columnNumber); let left = columnIndex * cwidth + 20; $template.css('left', left + 'px').css('top', '-15px').css('width', '12px').css('height', '12px'); $template.addClass(classname); $page.append($template); } } } else { if (firstBorder && firstBorder.className && firstBorder.className.indexOf('js-lsiten-border') > -1) { if ($placeholder.length > 0) { // 删除跨栏符 $placeholder.remove(); } } } } } else { let page = column.parentNode; if (page) { let $page = $(page); let columnIndex = parseInt(column.getAttribute('data-column-i')); let crossPlaceholder = '.js-cross-placeholder-' + columnIndex; let classname = 'js-cross-placeholder-' + columnIndex; let $placeholder = $page.find(crossPlaceholder); if ($placeholder.length > 0) { // 删除跨栏符 $placeholder.remove(); } } } }, /** * function 循环查找段落 */ _cycleFindParagraph: function (paragraph) { if (!paragraph) { return null; } let i = 0; while (i < 100 && (!paragraph.className || paragraph.className.indexOf('js-paragraph-view') < 0)) { let temp = paragraph.nextSibling; paragraph.parentNode.removeChild(paragraph); paragraph = temp; i++; } let firstContent = paragraph.firstChild; if (firstContent && firstContent.className && firstContent.className.indexOf('js-answer-header') > -1) { let temp = paragraph.nextSibling; paragraph = temp; return this._cycleFindParagraph(paragraph); } return paragraph || null; }, /** * @param {DomElement} $column 栏dom */ _checkColumnOut($column) { let $paragraphs = $column.find('.js-paragraph-view'); let cSize = $column.getSizeData(); let i = $paragraphs.length - 1; let $moves = []; while (i >=0 ) { let $paragraph = $($paragraphs[i]); let pSize = $paragraph.getSizeData(); if (pSize.top >= cSize.bottom) { $moves.push($paragraph); } else if (pSize.bottom >= cSize.bottom) { this._splitParagraph($moves, $paragraph, cSize, $column); } i--; } if ($moves.length > 0) { let nextColumn = this._getNextColumn($column, true); if (nextColumn.column) { let $firsParagraph = this._getFirstPargraph(nextColumn.column); if ($firsParagraph) { $moves.forEach(item => { this._insertParagraph(item, $firsParagraph); }) } else { let moveIndex = $moves.length - 1; while (moveIndex >=0 ) { nextColumn.column.append($moves[moveIndex]); moveIndex--; } } nextColumn.page._checkColumnOut(nextColumn.column); // 跨栏符检测 let $lastParagraph = $paragraphs[$paragraphs.length - 1]; if (isEmptyElement($lastParagraph)) { $lastParagraph.remove(); } this._checkIsCross($firsParagraph, nextColumn.column); this._updateCrossColumn(nextColumn.column); this._updateObjectColumnHeight(nextColumn.column[0]); } // 跨栏符检测 this._checkIsCross($($paragraphs[$paragraphs.length - 1]), $column); this._updateCrossColumn($column); } }, /** * function 更新客观题栏高 */ _updateObjectColumnHeight: function (checkColumn) { let updateNextPara = this._cycleFindParagraph(checkColumn.firstChild); if (updateNextPara) { this._updateObjectColumnHeightByBorder(updateNextPara); // 更新栏高 结束 this._updateObjectColumnBorder(updateNextPara); } }, /** * function 更新客观题栏行线 */ _updateObjectColumnHeightByBorder: function (border) { let cententHeight = 0; $(border).find('.js-option-column').forEach(column => { let contentSize = $(column.firstChild).getSizeData(); cententHeight = contentSize.height; $(column).css('min-height', cententHeight + 'px'); }); }, /** * function 更新客观题栏行线 */ _updateObjectColumnBorder: function (border) { let rowIndex = 0; $(border).find('.js-options-row').forEach(row => { if (rowIndex > 0) { $(row).css('border-top', '1px solid #000'); } rowIndex++; }) }, /** * function 插入段落 * @param {DomElement} $insertParagraph 需要插入的段落 * @param {DomElement} $firsParagraph 插入该段之前 */ _insertParagraph: function ($insertParagraph, $firsParagraph) { let insertClass = $insertParagraph.attr('class'); let firstClass = $firsParagraph.attr('class'); if (insertClass && firstClass && insertClass.indexOf('js-split-paragraph') >-1 && firstClass.indexOf('js-split-paragraph') >-1) { let insertLast = $insertParagraph[0].lastChild; let firstFirst = $firsParagraph[0].firstChild; this._mergeSplitParagraph(insertLast, firstFirst, $insertParagraph); } else { $insertParagraph.insertBefore($firsParagraph); } }, /** * function 检测最后一段是否需要跨栏 * @param {DomElement} $lastParagraph 该栏最后一段 * @param {DomElement} $column 该栏 */ _checkIsCross: function ($lastParagraph, $column) { if (!$lastParagraph || !$lastParagraph[0]) { return false; } let $prevColumn = this._getPrevColumn_v2($column); let $nextColumn = this._getNextColumn_v2($column); let currentIndex = $lastParagraph.attr('data-index'); let prevIndex = ''; let nextIndex = ''; if ($prevColumn) { let $paragraphs = $prevColumn.find('.js-paragraph-view'); let lastIndex = $paragraphs.length - 1; if (lastIndex) { prevIndex = $paragraphs[lastIndex].getAttribute('data-index'); } } if ($nextColumn) { let $nextParagraphs = $nextColumn.find('.js-paragraph-view'); let nextLastIndex = $nextParagraphs.length - 1; if (nextLastIndex) { nextIndex = $nextParagraphs[nextLastIndex].getAttribute('data-index'); } } if (currentIndex === prevIndex || currentIndex === nextIndex) { $lastParagraph.addClass('js-split-paragraph'); } else { $lastParagraph.removeClass('js-split-paragraph'); } }, /** * function 获取该栏上一栏 * @param {DomElement} $column 该栏 */ _getPrevColumn_v2: function ($column) { let prev = $column[0].previousSibling; if (prev && prev.className && prev.className.indexOf('js-column') > -1) { return $(prev); } let prevIndex = this.pageIndex - 1; if (prevIndex < 0) { return false; } let prevPage = this.manage.pages[prevIndex]; let lastColumnIndex = prevPage.$colums.length - 1; return prevPage.$colums[lastColumnIndex] || false; }, /** * function 获取该栏下一栏 * @param {DomElement} $column 该栏 */ _getNextColumn_v2: function ($column) { let next = $column[0].nextSibling; if (next && next.className && next.className.indexOf('js-column') > -1) { return $(next); } let nextIndex = this.pageIndex + 1; if (nextIndex < 0) { return false; } let nextPage = this.manage.pages[nextIndex]; if (!nextPage) { return false; } return nextPage.$colums[0] || false; }, /** * function 插入内容在该dom之前 * @param {DomElement} */ _insertDomBeforeByFirst: function ($paragraph, first) { $paragraph.childNodes().forEach(child => { $(child).insertBefore($(first)); }) }, /** * function 合并拆分过的段落 * @param {node} 上一段最后一个dom * @param {node} 下一段第一个dom * @param {DomElement} 需要插入的段落 */ _mergeSplitParagraph: function (insertLast, firstFirst, $Allparagraph) { if (!insertLast) { return false; } if (insertLast.className && insertLast.className.indexOf('js-lsiten-line') > -1) { // 普通行处理 this._insertDomBeforeByFirst($Allparagraph, firstFirst); } else if (insertLast.className && insertLast.className.indexOf('js-lsiten-border') > -1) { // 框处理 if (firstFirst && firstFirst.className && firstFirst.className.indexOf('js-lsiten-border') > -1) { // 如果下一段第一个dom是框 let borderId = insertLast.getAttribute('data-id'); let nextBorderId = firstFirst.getAttribute('data-id'); if (borderId === nextBorderId) { // 如果两个框是同一个框 let borderType = parseInt(firstFirst.getAttribute('data-type')); if (borderType === 1) { let objectLastRow = insertLast.lastChild; let objectFirstRow = firstFirst.firstChild; let lastRowId = objectLastRow.getAttribute('data-id'); let firstRowId = objectFirstRow.getAttribute('data-id'); if (lastRowId === firstRowId) { let lastRowColumns = $(objectLastRow).find('.js-option-column'); let firstRowColumns = $(objectFirstRow).find('.js-option-column'); let rowColumnLength = lastRowColumns.length; for (let rowColumnIndex = 0; rowColumnIndex < rowColumnLength; rowColumnIndex++) { if (firstRowColumns[rowColumnIndex].firstChild && firstRowColumns[rowColumnIndex].firstChild.firstChild) { this._insertDomBeforeByFirst($(lastRowColumns[rowColumnIndex].firstChild), firstRowColumns[rowColumnIndex].firstChild.firstChild); } else { if (lastRowColumns[rowColumnIndex].firstChild && firstRowColumns[rowColumnIndex].firstChild) { let lastRowColumnsChilds = $(lastRowColumns[rowColumnIndex].firstChild).childNodes(); let lastRowColumnsChildsIndex = lastRowColumnsChilds.length - 1; while(lastRowColumnsChildsIndex >= 0) { firstRowColumns[rowColumnIndex].firstChild.appendChild(lastRowColumnsChilds[lastRowColumnsChildsIndex]); lastRowColumnsChildsIndex--; } } } } $(objectLastRow).remove(); this._insertDomBeforeByFirst($(insertLast), objectFirstRow); } else { if (!this.isObjectEmpty(insertLast)) { this._insertDomBeforeByFirst($(insertLast), objectFirstRow); } } } else if (borderType === 2) { let insertLastQuestion = insertLast.firstChild.lastChild; let firstFirstQuestion = firstFirst.firstChild.firstChild; this._mergeSplitBorder(insertLastQuestion, firstFirstQuestion, $(insertLast)); this._insertDomBeforeByFirst($Allparagraph, firstFirst); } } else { // 如果不是同一个框 this._insertDomBeforeByFirst($Allparagraph, firstFirst); } } else { // 如果下一段第一个dom不是框 this._insertDomBeforeByFirst($Allparagraph, firstFirst); } } else { let parentNode = insertLast.parentNode; $(insertLast).remove(); this._mergeSplitParagraph(parentNode.lastChild, firstFirst); } }, /** * function 判断客观题框是否为空 * @param {node} object 客观题框 */ isObjectEmpty: function (object) { let $object = $(object); $object.childNodes().forEach(row => { if(this.isObjectRowEmpty(row)) { $(row).remove(); } }) return isEmptyElement(object); }, /** * function 判断客观题框行是否为空 * @param {node} objectRow 客观题行 */ isObjectRowEmpty: function (objectRow) { let $objectRow = $(objectRow); let status = true; $objectRow.childNodes().forEach(colum => { if (!isEmptyElement(colum.firstChild)) { status = false; } }) return status; }, /** * function 合并框 * @param {node} lQuestion 上一段最后一个问题 * @param {node} fQuestion 下一段第一个问题 * @param {DomElement} $Allborder 该框所有dom */ _mergeSplitBorder: function (lQuestion, fQuestion, $Allborder) { if (!lQuestion) { return false; } if (lQuestion.className && lQuestion.className.indexOf('js-lsiten-line') > -1) { // 普通行处理 this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } else if (lQuestion.className && lQuestion.className.indexOf('js-lsiten-options-box') > -1) { // 选作题组 this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } else if (lQuestion.className && lQuestion.className.indexOf('js-lsiten-question') > -1) { // 主观题才需要合并 let type = parseInt(lQuestion.getAttribute('data-type')); if (type > 2) { if (fQuestion.className && fQuestion.className.indexOf('js-lsiten-question') > -1) { let questionId = lQuestion.getAttribute('data-id'); let nextQuestionId = fQuestion.getAttribute('data-id'); if (questionId === nextQuestionId) { // 不是同一个题 if (type === 3) { // 客观题 let $lquestion = $(lQuestion); let fQuestionFirst = fQuestion.firstChild; this._insertDomBeforeByFirst($lquestion, fQuestionFirst); $lquestion.remove(); this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } else if (type === 4) { // 作文题 let questionContent = lQuestion.lastChild; let firstContent = fQuestion.firstChild; if (questionContent.className && questionContent.className.indexOf('lsiten-title') > -1) { if (firstContent.className && firstContent.className.indexOf('lsiten-title') > -1) { let $writtingTitle = $(questionContent); this._insertDomBeforeByFirst($writtingTitle, firstContent.firstChild); $writtingTitle.remove(); this._insertDomBeforeByFirst($(lQuestion), firstContent); $(lQuestion).remove(); this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } else { this._insertDomBeforeByFirst($(lQuestion), firstContent); $(lQuestion).remove(); this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } } else if (questionContent.className && questionContent.className.indexOf('lsiten-border-box') > -1) { if (firstContent.className && firstContent.className.indexOf('lsiten-border-box') > -1) { let $writtingRows = $(questionContent); this._insertDomBeforeByFirst($writtingRows, firstContent.firstChild); $writtingRows.remove(); this._insertDomBeforeByFirst($(lQuestion), firstContent); $(lQuestion).remove(); this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } else { this._insertDomBeforeByFirst($(lQuestion), firstContent); $(lQuestion).remove(); this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } } else { questionContent && questionContent.parentNode.removeChild(questionContent); } } } else { // 不是同一个题 this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } } else { // 下一段第一个不是一个问题 this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } } else { // 客观题处理 this._insertDomBeforeByFirst($($Allborder[0].firstChild), fQuestion); $Allborder.remove(); } } else { let parentNode = lQuestion.parentNode; $(lQuestion).remove(); this._mergeSplitBorder(parentNode.lastChild, fQuestion, $Allborder); } }, /** * function 检测内容是否需要回退 */ _checkContentBack: function () { let $columns = this.$colums; // 备用 let maxHeight = parseInt(this._pagesHeight[this.editor.pageSize]); $columns.forEach($column => { this._checkColumnBack($column); }); this.manage._checkRemovePage(); }, /** * function 检测该段落是否为答题卡头 * @param {DomElement} 需要检测的段落 */ isHeadParagraph: function ($paragraph) { if (!$paragraph || !$paragraph[0]) { return false; } let firstChild = $paragraph[0].firstChild; return firstChild && firstChild.className && firstChild.className.indexOf('js-answer-header') > -1; }, /** * function 检测栏是否需要回退 * @param {DomElement} $column 需要检测的栏 */ _checkColumnBack: function ($column) { let $paragraphs = $column.find('.js-paragraph-view'); let cSize = $column.getSizeData(); let i = $paragraphs.length - 1; let $moves = []; if (!$paragraphs[i]) { return false; } let $lastParagraph = $($paragraphs[i]); let lastSize = $lastParagraph.getSizeData(); let diff = cSize.bottom - lastSize.bottom; if (diff > this.lineHeight) { let nextColumn = this._getNextColumn($column, false); // 如果有下一页,进行检测 if (nextColumn.column) { let $nextParagraphs = nextColumn.column.find('.js-paragraph-view'); let j = 0; let nextParagraphLength = $nextParagraphs.length || 0; while (j < nextParagraphLength) { if (j > 0) { let prevIndex = j - 1; if ($nextParagraphs[prevIndex] && !isEmptyElement($nextParagraphs[prevIndex]) && !this.isHeadParagraph($($nextParagraphs[prevIndex]))) { j++; continue; } } if ($nextParagraphs[j]) { let $paragraph = $($nextParagraphs[j]); if ($paragraph && !this.isHeadParagraph($paragraph)) { let pSize = $paragraph.getSizeData(); if (pSize.height < diff) { $moves.push($paragraph); } else { let size = { diff: diff } this._prevParagraph($moves, $paragraph, size, $lastParagraph); } } } j++; } let lastPid = $lastParagraph.attr('data-index'); let lastBorderItem = $lastParagraph[0].lastChild; let lastIsBorder = lastBorderItem && lastBorderItem.className && lastBorderItem.className.indexOf('js-lsiten-border') > -1; $moves.forEach($paragraphITem => { let currentPid = $paragraphITem.attr('data-index'); if (lastPid === currentPid) { $paragraphITem.childNodes().forEach(item => { if (item.nodeType === 3) { $paragraph[0].removeChild(item); } else { let $item = $(item); let itemClass = $item.attr('class'); if (itemClass && itemClass.indexOf('js-lsiten-line') > -1) { // 普通行 $lastParagraph.append($item); } else if (itemClass && itemClass.indexOf('js-lsiten-border') > -1) { // 框处理 if (lastIsBorder) { let borderId = lastBorderItem.getAttribute('data-id'); let currentBorderId = $item.attr('data-id'); if (currentBorderId === borderId) { let borderType = parseInt($item.attr('data-type')); if (borderType === 1) { // 客观题处理 $item.childNodes().forEach(objectRow => { if (!objectRow.previousSibling) { let lastRow = lastBorderItem.lastChild; let firstRowId = objectRow.getAttribute('data-id'); let lastRowId = lastRow.getAttribute('data-id'); if (firstRowId === lastRowId) { let objectColumns = $(objectRow).find('.js-option-column'); // 以第一栏的为基准 let objectFirstColumn = objectColumns[0]; $(objectFirstColumn.firstChild).childNodes().forEach(objectQuestion => { if (!objectQuestion.previousSibling) { this._mergeObjectRow(objectColumns, lastRow); } }) } else { lastBorderItem.appendChild(objectRow); } } }) $item.remove(); this._updateObjectColumnBorder(lastBorderItem); this._updateObjectColumnHeightByBorder(lastBorderItem); } else if (borderType === 2) { $($item[0].firstChild).childNodes().forEach(borderItem => { if (borderItem.className) { if (borderItem.className.indexOf('js-lsiten-question') > -1) { let qustionType = parseInt(borderItem.getAttribute('data-type')); let lastQuestionItem = lastBorderItem.lastChild; let lastQuestionId = lastQuestionItem.getAttribute('data-id'); let currentQuestionId = borderItem.getAttribute('data-id'); if (lastQuestionId && currentQuestionId && currentQuestionId === lastQuestionId) { if (qustionType === 3) { $(borderItem).childNodes().forEach(subjectItem => { lastQuestionItem.appendChild(subjectItem); }) } else if (qustionType === 4) { $(borderItem).childNodes().forEach(writtingItem => { if (writtingItem.className.indexOf('lsiten-title') > -1) { let $prevWrittingTitleItem = $(lastQuestionItem).find('.lsiten-title'); let needMergeItem = true; if (!$prevWrittingTitleItem.length) { needMergeItem = false; $prevWrittingTitleItem = $($prevWrittingTitleItem); } else { needMergeItem = false; $prevWrittingTitleItem = $(writtingItem).clone(false); } $(writtingItem).childNodes().forEach(writtingTitleItem => { $prevWrittingTitleItem[0].appendChild(writtingTitleItem); }) if (needMergeItem && !isEmptyElement($prevWrittingTitleItem[0])) { lastQuestionItem.appendChild($prevWrittingTitleItem[0]); } } else if (writtingItem.className.indexOf('lsiten-border-box') > -1) { let $prevWrittingRowsItem = $(lastQuestionItem).find('.lsiten-border-box'); let needMergeItem = true; if (!$prevWrittingRowsItem.length) { needMergeItem = false; $prevWrittingRowsItem = $($prevWrittingRowsItem); } else { needMergeItem = false; $prevWrittingRowsItem = $(writtingItem).clone(false); } $(writtingItem).childNodes().forEach(writtingRowItem => { $prevWrittingRowsItem[0].appendChild(writtingRowItem); }) if (needMergeItem && !isEmptyElement($prevWrittingRowsItem[0])) { lastQuestionItem.appendChild($prevWrittingRowsItem[0]); } } }) } else { $(borderItem).remove(); } $(borderItem).remove(); } else { lastBorderItem.firstChild.appendChild(borderItem); } } else if (itemClass && itemClass.indexOf('js-lsiten-options-box') > -1) { // 选作题组【回退】 lastBorderItem.firstChild.appendChild(borderItem); } else if (borderItem.className.indexOf('js-lsiten-line') > -1) { lastBorderItem.firstChild.appendChild(borderItem); } else { $(borderItem).remove(); } } }) $item.remove(); } } else { $lastParagraph.append($item); } } else { $lastParagraph.append($item); } } else { $item.remove(); } } }) $paragraphITem.remove(); } else { $paragraphITem.insertAfter($lastParagraph); } }) // 跨栏符检测 this._checkIsCross($($paragraphs[$paragraphs.length - 1]), $column); this._checkIsCross($($nextParagraphs[0]), nextColumn.column); this._updateCrossColumn($column); this._updateCrossColumn(nextColumn.column); this._updateObjectColumnHeight(nextColumn.column[0]); } } }, /** * function 检测段落是否需要上移 * @param {array} $moves 需要移动的段落数组 * @param {DomElement} $paragraph 需要检测的段落 * @param {object} size 可以上移的空间 * @param {DomElement} $lastParagraph 该段最后一段 */ _prevParagraph: function ($moves, $paragraph, size, $lastParagraph) { let lastClass = $lastParagraph.attr('class'); let currentClass = $paragraph.attr('class'); let lastPid = $lastParagraph.attr('data-index'); let currentPid = $paragraph.attr('data-index'); if (lastClass && lastClass.indexOf('js-split-paragraph') > -1) { if (currentClass && currentClass.indexOf('js-split-paragraph') > -1 && lastPid === currentPid) { // 如果两个段落需要合并 let $prevParagraph = $lastParagraph; $paragraph.childNodes().forEach(item => { if (item.nodeType === 3) { $paragraph[0].removeChild(item); } else { let $item = $(item); let itemClass = $item.attr('class'); if (itemClass && itemClass.indexOf('js-lsiten-line') > -1) { // 普通行 let height = $item.getSizeData().height; if (height < size.diff) { $prevParagraph.append($item); size.diff -= height; } } else if (itemClass && itemClass.indexOf('js-lsiten-border') > -1) { // 框处理 let borderType = parseInt($item.attr('data-type')); if (borderType === 1) { // 客观题处理 this._prevObjectBorder($prevParagraph, size, $item, $lastParagraph, true); } else if (borderType === 2) { // 主观观题处理 this._prevBorder($prevParagraph, size, $item, $lastParagraph, true); } } else { $item.remove(); } } }) } else { // 两段落不需要合并 let $prevParagraph = $paragraph.clone(false); $paragraph.childNodes().forEach(item => { if (item.nodeType === 3) { $paragraph[0].removeChild(item); } else { let $item = $(item); let itemClass = $item.attr('class'); if (itemClass && itemClass.indexOf('js-lsiten-line') > -1) { let height = $item.getSizeData().height; if (height < size.diff) { $prevParagraph.append($item); size.diff -= height; } } else if (itemClass && itemClass.indexOf('js-lsiten-border') > -1) { // 框处理 let borderType = parseInt($item.attr('data-type')); if (borderType === 1) { // 客观题处理 this._prevObjectBorder($prevParagraph, size, $item, $lastParagraph, false); } else if (borderType === 2) { this._prevBorder($prevParagraph, size, $item, $lastParagraph, false); } } else { $item.remove(); } } }) if (!isEmptyElement($prevParagraph[0])) { $moves.push($prevParagraph); } } } else { // 两段落不需要合并 let $prevParagraph = $paragraph.clone(false); $paragraph.childNodes().forEach(item => { if (item.nodeType === 3) { $paragraph[0].removeChild(item); } else { let $item = $(item); let itemClass = $item.attr('class'); if (itemClass && itemClass.indexOf('js-lsiten-line') > -1) { let height = $item.getSizeData().height; if (height < size.diff) { $prevParagraph.append($item); size.diff -= height; } } else if (itemClass && itemClass.indexOf('js-lsiten-border') > -1) { // 框处理 let borderType = parseInt($item.attr('data-type')); if (borderType === 1) { // 客观题处理 this._prevObjectBorder($prevParagraph, size, $item, $lastParagraph, false); } else if (borderType === 2) { this._prevBorder($prevParagraph, size, $item, $lastParagraph, false); } } else { $item.remove(); } } }) if (!isEmptyElement($prevParagraph[0])) { $moves.push($prevParagraph); } } if (isEmptyElement($paragraph[0])) { $paragraph.remove(); } }, /** * function 处理需要上移的框 * @param {DomElement} $prevParagraph 前移段落暂存 * @param {object} size 可移空间 * @param {DomElement} $border 需要处理的框 * @param {DomElement} $lastParagraph 最后一段dom * @param {boolean} 是否需要合并 */ _prevObjectBorder: function ($prevParagraph, size, $border, $lastParagraph, isMerge) { let lastCentent = $lastParagraph[0].lastChild; if (lastCentent && lastCentent.className && lastCentent.className.indexOf('js-lsiten-border') > -1) { let prevBid = $border.attr('data-id'); let bid = $(lastCentent).attr('data-id'); if (prevBid === bid) { let $prevBorder = $border.clone(false); if (isMerge) { $prevBorder = $($prevParagraph[0].lastChild); } $border.childNodes().forEach(row => { if (!row.previousSibling) { let lastRow = lastCentent.lastChild; let firstRowId = row.getAttribute('data-id'); let lastRowId = lastRow.getAttribute('data-id'); if (firstRowId === lastRowId) { let columns = $(row).find('.js-option-column'); // 以第一栏的为基准计算 let firstColumn = columns[0]; $(firstColumn.firstChild).childNodes().forEach(question => { if (!question.previousSibling) { let height = $(question).getSizeData().height + 16; if (height < size.diff) { this._mergeObjectRow(columns, lastRow); size.diff -= height; } } }) if (isEmptyElement(firstColumn.firstChild)) { $(row).remove(); } } else { // 客观题每一个row的高度 let rowOutsize = 24; size.diff -= rowOutsize; let columns = $(row).find('.js-option-column'); // 以第一栏的为基准计算 let firstColumn = columns[0]; let prevRow = row.cloneNode(false) $(firstColumn.firstChild).childNodes().forEach(question => { if (!question.previousSibling) { let height = $(question).getSizeData().height + 16; if (height < size.diff) { this._mergeObjectRow(columns, prevRow); size.diff -= height; } } }) if (!isEmptyElement(prevRow)) { $prevBorder[0].appendChild(prevRow); } size.diff += rowOutsize; if (isEmptyElement(firstColumn.firstChild)) { $(row).remove(); } } } }) if (!isMerge && !isEmptyElement($prevBorder[0])) { $prevParagraph.append($prevBorder); } if (isEmptyElement($border[0])) { $border.remove(); } this._updateObjectColumnBorder(lastCentent); this._updateObjectColumnHeightByBorder(lastCentent); } } }, /** * function 合并主观题行 * @param {Array} columns 需要处理的栏 * @param {node} lastRow 上一段最后一框最后一行 */ _mergeObjectRow: function (columns, lastRow) { let lastColumns = $(lastRow).find('.js-option-column'); let length = columns.length; for (let i =0; i < length; i++) { if (columns[i].firstChild.childNodes[0]) { if (lastColumns[i]) { lastColumns[i].firstChild.appendChild(columns[i].firstChild.childNodes[0]); } else { let prevColumn = columns[i].cloneNode(false); let prevColumnContent = columns[i].firstChild.cloneNode(false); prevColumn.appendChild(prevColumnContent); prevColumnContent.appendChild(columns[i].firstChild.childNodes[0]); lastRow.appendChild(prevColumn); } } } }, /** * function 处理需要上移的框 * @param {DomElement} $prevParagraph 前移段落暂存 * @param {object} size 可移空间 * @param {DomElement} $border 需要处理的框 * @param {DomElement} $lastParagraph 最后一段dom * @param {boolean} 是否需要合并 */ _prevBorder: function ($prevParagraph, size, $border, $lastParagraph, isMerge) { let lastCentent = $lastParagraph[0].lastChild; if (lastCentent && lastCentent.className && lastCentent.className.indexOf('js-lsiten-border') > -1) { let prevBid = $border.attr('data-id'); let bid = $(lastCentent).attr('data-id'); if (prevBid === bid) { let $prevBorder = $border.clone(false); let $prevBorderContent = $($border[0].firstChild).clone(false); $prevBorder.append($prevBorderContent); if (isMerge) { $prevBorder = $($prevParagraph[0].lastChild); $prevBorderContent = $prevBorder[0].firstChild; } this._prevQuestions($prevBorder, size, $border, $(lastCentent)); if (!isMerge && !isEmptyElement($prevBorderContent[0])) { $prevParagraph.append($prevBorder); } } else { let borderSize= $border.getSizeData(); if (borderSize.height < size.diff) { $prevParagraph.append($border); size.diff -= borderSize.height; } else { // 框的padding+margin+border let borderOutSize = 22; let $prevBorder = $border.clone(false); let $borderContent = $($border[0].firstChild); let $prevBorderContent = $borderContent.clone(false); $prevBorder.append($prevBorderContent); size.diff -= borderOutSize; $borderContent.childNodes().forEach(item => { if (!item.previousSibling) { if (item.className) { if (item.className.indexOf('js-lsiten-question') > -1) { let qustionType = parseInt(item.getAttribute('data-type')); if (qustionType === 3) { let $prevSubject = $(item).clone(false); this._prevSubjectQuestion($prevSubject, size, $(item), false); if (!isEmptyElement($prevSubject)) { $prevBorderContent[0].appendChild($prevSubject[0]); } } else if (qustionType === 4) { let $prevWritting = $(item).clone(false); this._prevWrittingQuestion($prevWritting, size, $(item), false); if (!isEmptyElement($prevWritting)) { $prevBorderContent[0].appendChild($prevWritting[0]); } } else { let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorderContent[0].appendChild(item); size.diff -= height; } } } else if (item.className.indexOf('js-lsiten-line') > -1) { let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorderContent[0].appendChild(item); size.diff -= height; } } else if (item.className.indexOf('js-lsiten-options-box') > -1) { // 选作题组【回退】 let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorderContent[0].appendChild(item); size.diff -= height; } } else { $(item).remove(); } } else { item && item.parentNode.removeChild(item); } } }) size.diff += borderOutSize; if (!isEmptyElement($prevBorderContent[0])) { $prevParagraph.append($prevBorder); } } } } else { // 框的padding+margin+border let borderOutSize = 22; let $prevBorder = $border.clone(false); let $borderContent = $($border[0].firstChild); let $prevBorderContent = $borderContent.clone(false); $prevBorder.append($prevBorderContent); size.diff -= borderOutSize; $borderContent.childNodes().forEach(item => { if (!item.previousSibling) { if (item.className) { if (item.className.indexOf('js-lsiten-question') > -1) { let qustionType = parseInt(item.getAttribute('data-type')); if (qustionType === 3) { let $prevSubject = $(item).clone(false); this._prevSubjectQuestion($prevSubject, size, $(item), false); if (!isEmptyElement($prevSubject)) { $prevBorderContent.appendChild($prevSubject[0]); } } else if (qustionType === 4) { let $prevWritting = $(item).clone(false); this._prevWrittingQuestion($prevWritting, size, $(item), false); if (!isEmptyElement($prevWritting)) { $prevBorderContent.appendChild($prevWritting[0]); } } else { let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorderContent.appendChild(item); size.diff -= height; } } } else if (item.className.indexOf('js-lsiten-line') > -1) { let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorderContent[0].appendChild(item); size.diff -= height; } } else if (item.className.indexOf('js-lsiten-options-box') > -1) { // 选作题组【回退】 let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorderContent[0].appendChild(item); size.diff -= height; } } else { $(item).remove(); } } else { item && item.parentNode.removeChild(item); } } }) size.diff += borderOutSize; if (!isEmptyElement($prevBorderContent[0])) { $prevParagraph.append($prevBorder); } } if (isEmptyElement($border[0].firstChild)) { $border.remove(); } }, /** * function 前移问题 * @param {DomElement} $prevBorder 前移框暂存 * @param {object} size 前移段落暂存 * @param {DomElement} $border 前移段落暂存 * @param {DomElement} $lastBorder 前段落最后一个框 * */ _prevQuestions: function ($prevBorder, size, $border, $lastBorder) { let lastQuestion = $lastBorder[0].firstChild.lastChild; let $borderContent = $($border[0].firstChild); $borderContent.childNodes().forEach(item => { if (!item.previousSibling) { if (item.className) { if (item.className.indexOf('js-lsiten-question') > -1) { let qustionType = parseInt(item.getAttribute('data-type')); let questionId = item.getAttribute('data-id'); if (lastQuestion.className && lastQuestion.className.indexOf('js-lsiten-question') > -1) { let lastQuestionId = lastQuestion.getAttribute('data-id'); if (questionId && lastQuestionId && lastQuestionId === questionId) { // 需要合并2个小问 if (qustionType === 3) { this._prevSubjectQuestion($(lastQuestion), size, $(item), true); } else if (qustionType === 4) { this._prevWrittingQuestion($(lastQuestion), size, $(item), true); } else { let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorder[0].firstChild.appendChild(item); size.diff -= height; } } } else { if (qustionType === 3) { let $prevSubject = $(item).clone(false); this._prevSubjectQuestion($prevSubject, size, $(item), false); if (!isEmptyElement($prevSubject[0])) { $prevBorder[0].firstChild.appendChild($prevSubject[0]); } } else if (qustionType === 4) { let $prevWritting = $(item).clone(false); this._prevWrittingQuestion($prevWritting, size, $(item), false); if (!isEmptyElement($prevWritting[0])) { $prevBorder[0].firstChild.appendChild($prevWritting[0]); } } else { let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorder[0].firstChild.appendChild(item); size.diff -= height; } } } } else { if (qustionType === 3) { let $prevSubject = $(item).clone(false); this._prevSubjectQuestion($prevSubject, size, $(item), false); if (!isEmptyElement($prevSubject[0])) { $prevBorder[0].firstChild.appendChild($prevSubject[0]); } } else if (qustionType === 4) { let $prevWritting = $(item).clone(false); this._prevWrittingQuestion($prevWritting, size, $(item), false); if (!isEmptyElement($prevWritting[0])) { $prevBorder[0].firstChild.appendChild($prevWritting[0]); } } else { let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorder[0].firstChild.appendChild(item); size.diff -= height; } } } } else if (item.className.indexOf('js-lsiten-line') > -1) { let height = $(item).getSizeData().height; if (height < size.diff) { $prevBorder[0].firstChild.appendChild(item); size.diff -= height; } } else { $(item).remove(); } } else { item && item.parentNode.removeChild(item); } } }) }, /** * function 前移主观题框 * @param {DomElement} $prevSubject 前移框暂存 * @param {object} size 可移动空间 * @param {DomElement} $subject 需要前移客观题处理 * @param {boolean} isMerge 是否需要合并 */ _prevSubjectQuestion: function ($prevSubject, size, $subject, isMerge) { $subject.childNodes().forEach(item => { let height = $(item).getSizeData().height; if (height < size.diff) { $prevSubject[0].appendChild(item); size.diff -= height; } if (isEmptyElement($subject[0])) { $subject.remove(); } }) }, /** * function 前移主观题框 * @param {DomElement} $prevWritting 前移框暂存 * @param {number} size 可移动空间 * @param {DomElement} $Writting 需要前移客观题处理 * @param {boolean} isMerge 是否需要合并 */ _prevWrittingQuestion: function ($prevWritting, size, $Writting, isMerge) { $Writting.childNodes().forEach(item => { if (item.className) { if (item.className.indexOf('lsiten-title') > -1) { let $prevWrittingTitle = null; let needApppend = true; if (isMerge) { $prevWrittingTitle = $prevWritting.find('.lsiten-title'); if ($prevWrittingTitle.length) { $prevWrittingTitle = $($prevWrittingTitle); needApppend = false; } else { $prevWrittingTitle = null; let needApppend = true; } } let $writtingTitle = $(item); $prevWrittingTitle = $prevWrittingTitle || $writtingTitle.clone(false); $writtingTitle.childNodes().forEach(titleItem => { if (titleItem.className && titleItem.className.indexOf('js-lsiten-line') > -1) { let height = $(titleItem).getSizeData().height; if (height < size.diff) { $prevWrittingTitle[0].appendChild(titleItem); size.diff -= height; } } else { titleItem && item.removeChild(titleItem); } }) if (needApppend && !isEmptyElement($prevWrittingTitle[0])) { $prevWritting.append($prevWrittingTitle); } if (isEmptyElement($writtingTitle[0])) { $writtingTitle.remove(); } } else if (item.className.indexOf('lsiten-border-box') > -1) { let $prevWrittingRows = null; let needApppend = true; if (isMerge) { $prevWrittingRows = $prevWritting.find('.lsiten-border-box'); if ($prevWrittingRows.length) { $prevWrittingRows = $($prevWrittingRows); needApppend = false; } else { $prevWrittingRows = null; needApppend = true; } } let $writtingRows = $(item); $prevWrittingRows = $prevWrittingRows || $writtingRows.clone(false); // 行的margin值 let rowOutSize = 8; $writtingRows.childNodes().forEach(rowItem => { if (rowItem.className && rowItem.className.indexOf('js-lsiten-writting-row') > -1) { let height = $(rowItem).getSizeData().height + rowOutSize; if (height < size.diff) { $prevWrittingRows[0].appendChild(rowItem); size.diff -= height; } } else { rowItem && item.removeChild(rowItem); } }) if (needApppend && !isEmptyElement($prevWrittingRows[0])) { $prevWritting.append($prevWrittingRows); } if (isEmptyElement($writtingRows[0])) { $writtingRows.remove(); } } } }) if (isEmptyElement($Writting[0])) { $Writting.remove(); } }, /** * function 检测内容是否超出 */ _checkContentOut: function () { let $columns = this.$colums; // 备用 let maxHeight = parseInt(this._pagesHeight[this.editor.pageSize]); $columns.forEach($column => { this._checkColumnOut($column); }); }, /** * function 获取第一段 */ _getFirstPargraph: function (column) { let $paragraphs = column.find('.js-paragraph-view'); let firstParagraph = $paragraphs[0]; if (!firstParagraph) { return false; } let firstChild = firstParagraph.firstChild; if (firstChild && firstChild.className && firstChild.className.indexOf('js-answer-header') > -1) { firstParagraph = $paragraphs[1]; } return firstParagraph ? $(firstParagraph): false; }, /** * function 插入dom * @param {DomElement} $nextDom 下一栏暂存 * @param {DomElement} $dom 需要插入的dom */ insertDom($nextDom, $dom) { let firstChild = $nextDom[0].firstChild; if (firstChild) { $dom.insertBefore($(firstChild)); } else { $nextDom.append($dom); } }, /** * function 拆分段落 * @param $moves {Array} 需要移动的数组 * @param $paragraph {DomElement} 需要切分的段落 * @param cSize {Object} 段落尺寸数据 * @param $column {DomElement} 当前栏 */ _splitParagraph: function ($moves, $paragraph, cSize, $column) { let $nextParagraph = $paragraph.clone(false); let childs = $paragraph[0].childNodes; let index = childs.length - 1; while (index >= 0) { let line = childs[index]; if (line && line.className) { if (line.className.indexOf('js-lsiten-line') > -1) { // 普通一行 let $line = $(line); let lineSize = $line.getSizeData(); if (lineSize.top >= cSize.bottom) { this.insertDom($nextParagraph, $line); } } else if (line.className.indexOf('js-lsiten-border') > -1) { // 题框 this._splitBorder($nextParagraph, $(line), cSize); } else { $(line).remove(); } } else { line && $paragraph[0].removeChild(line); } index--; } if ($nextParagraph.childNodes().length > 0) { $paragraph.addClass('js-split-paragraph'); $nextParagraph.addClass('js-split-paragraph'); $moves.push($nextParagraph); } }, /** * function 获取下一栏 * @param {DomElement} $column 当前栏 * @param {boolean} isAddpage 是否需要新增页 */ _getNextColumn: function ($column, isAddPage) { let nextColumnIndex = parseInt($column.attr('data-column-i')) + 1; let $nextColumn = this.$colums[nextColumnIndex]; if ($nextColumn) { return { page: this, column: $nextColumn }; } else { let page = this._getNextPage(isAddPage); if (page) { $nextColumn = page.$colums[0]; return { page: page, column: $nextColumn }; } else { return { page: false, column: false }; } } }, /** * function 获取下一页对象 * @param {Boolean} isAddPage 如果没有是否添加一页 */ _getNextPage: function (isAddPage) { let nextPageIndex = this.pageIndex + 1; let page = this.manage.getNextPageByKey(nextPageIndex, isAddPage) return page; }, /** * function 拆分框 * @param $nextParagraph {DomElement} 下一段暂存 * @param $border {DomElement} 需要切分的框 * @param cSize {Object} 段落尺寸数据 */ _splitBorder: function ($nextParagraph, $border, cSize) { let $splitBorder = this.questionTools._splitBorder($border, cSize); if ($splitBorder) { this.insertDom($nextParagraph, $splitBorder); } }, _pagesHeight: { 'A4': '970px', 'A3': '970px' }, _pagesWidth: { 'A4': 653, 'A3': 1447 } } export default yzPage