lsiten пре 6 година
родитељ
комит
88f07b508c
2 измењених фајлова са 561 додато и 1 уклоњено
  1. 80 1
      src/js/yzPage.js
  2. 481 0
      src/js/yzPageManager.js

+ 80 - 1
src/js/yzPage.js

@@ -277,10 +277,16 @@ yzPage.prototype = {
           }
           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);
       }
 
@@ -338,6 +344,76 @@ yzPage.prototype = {
     }
   },
   /**
+   * 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}
    */
@@ -589,7 +665,8 @@ yzPage.prototype = {
           if (j > 0) {
             let prevIndex = j - 1;
             if ($nextParagraphs[prevIndex] && !isEmptyElement($nextParagraphs[prevIndex]) && !this.isHeadParagraph($($nextParagraphs[prevIndex]))) {
-              return true;
+              j++;
+              continue;
             }
           }
           if ($nextParagraphs[j]) {
@@ -743,6 +820,8 @@ yzPage.prototype = {
           }
         })
         // 跨栏符检测
+        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]); 

+ 481 - 0
src/js/yzPageManager.js

@@ -197,6 +197,487 @@ yzPageManager.prototype = {
     this._delEvent();
 
     this._contentchangeEvent();
+
+    // 框内事件菜单
+    this._borderEvent();
+  },
+  /**
+   * function 框相关事件
+   */
+  _borderEvent: function () {
+    let _this = this;
+    const $textElem = this.$el;
+    Jquery($textElem[0]).on('contextmenu','.js-lsiten-border', (e) => {
+      this._createContextMenu(e);
+    })
+  },
+  /**
+   * fucntion 创建菜单
+   * @param {event} e 事件对象
+   * @param {array} menus 数组对象
+   */
+  _createContextMenu: function (e, menus) {
+    let $target = $(e.target);
+    let $border = getParentByClassname($target, 'js-lsiten-border');
+    let movex=e.pageX;
+    let movey=e.pageY;
+    !menus && (menus = []);
+    this._createMenu(movex, movey, $border, menus);
+    e.preventDefault();
+  },
+  /**
+   * function 创建菜单列表
+   * @param {number} x x轴坐标 
+   * @param {number} y y轴坐标 
+   * @param {DomElement} $border 该框 
+   * @param {array} menus 数组对象 
+   */
+  _createMenu: function (x, y, $border, menus) {
+    let $menu = $('<div class="js-lsiten-contentmenus"></div>');
+    $menu.css('width', '100px')
+         .css('height', 'auto')
+         .css('background', '#fff')
+         .css('position', 'absolute')
+         .css('z-index', '9999')
+         .css('outline', 'none')
+         .css('top', y + 'px')
+         .css('border', '1px solid #e4dddd')
+         .css('padding', '0')
+         .css('box-shadow', '0 3px 7px rgba(0, 0, 0, 0.1)')
+         .css('left', x + 'px');
+    $menu.attr('tabIndex', 1);
+
+    menus.forEach(item => {
+      let $menuItem = $('<div>' + item.name + '</div>');
+      $menuItem.css('cursor', 'pointer')
+           .css('text-align', 'center')
+           .css('border-bottom', '1px solid #e8e3e3')
+           .css('padding', '5px 0');
+      $menu.append($menuItem);
+      if (item.click && typeof item.click === 'function') {
+        item.click($menuItem);
+      }
+    })
+    this._commonMenus($menu, $border);
+    $(document.body).append($menu);
+    $menu.focus();
+    Jquery($menu[0]).on('blur', (e) => {
+      $menu && $menu.remove();
+    })
+  },
+  /**
+   * function 创建菜单列表
+   * @param {DomElement} $menu menu的dom
+   * @param {DomElement} $border 框的dom
+   */
+  _commonMenus: function ($menu, $border) {
+    // 添加文本框开始
+    let $addText = $('<div>加文本框</div>');
+    $addText.css('cursor', 'pointer')
+           .css('text-align', 'center')
+           .css('border-bottom', '1px solid #e8e3e3')
+           .css('padding', '5px 0');
+    $menu.append($addText);
+    $addText.on('click', () => {
+      this._checkNeedBackStatus = true;
+      let $prevBorders = this._findPrevBorders($border);
+      let lastBorderIndex = $prevBorders.length - 1;
+      let $baiscBorder = lastBorderIndex >= 0 ? $($prevBorders[lastBorderIndex]) : $border;
+      let $currentParagraph = getParentByClassname($baiscBorder, 'js-paragraph-view');
+      if ($currentParagraph) {
+        let index = $currentParagraph.attr('data-index');
+        let pageIndex = parseInt(index.split('-')[0]);
+        if (pageIndex > -1) {
+          let currentPage = this.pages[pageIndex];
+          if (currentPage) {
+            let $paragraph = $('<div class="js-paragraph-view"></div>');
+            $paragraph.append(gennerOneLine());
+            $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 = pageIndex + '-' + currentPage.paragraphIndex++;
+            $paragraph.attr('data-index', index);
+            $paragraph.insertBefore($currentParagraph);
+            setTimeout(() => {
+              $paragraph.focus();
+            }, 100)
+          }
+        } else {
+          console.log('error');
+        }
+      } else {
+        console.log('error')
+      }
+
+      $menu[0].blur();
+    })
+    // 添加文本框结束
+    // 删除开始
+    // let $delete = $('<div>删除框</div>');
+    // $delete.css('cursor', 'pointer')
+    //        .css('text-align', 'center')
+    //        .css('padding', '5px 0');
+    // $menu.append($delete);
+
+    // $delete.on('click', () => {
+    //   this._checkNeedBackStatus = true;
+    //   // 如果是第一栏第一个框不允许删除
+    //   let $currentParagraph = getParentByClassname($border, 'js-paragraph-view');
+    //   let currentParagphChilds = $currentParagraph[0].childNodes;
+    //   if (currentParagphChilds.length === 1 && $(currentParagphChilds[0]).equal($border)) {
+    //     let $currentColumn = getParentByClassname($border, 'js-column');
+    //     let $paragraphs = $currentColumn.find('.js-paragraph-view');
+    //     let firstParagraph = this._cycleFindParagraph($paragraphs[0]);
+    //     if (firstParagraph && $(firstParagraph).equal($currentParagraph)) {
+    //       let pageIndex =  parseInt($currentColumn.attr('data-column-i'));
+    //       if (this.pages.length === 1 && pageIndex === 0) {
+    //         this.editor.message.showMessage('第一页第一个框不能删除!');
+    //         $menu[0].blur();
+    //         return false;
+    //       }
+    //     }
+    //   }
+    //   let $prevBorders = this._findPrevBorders($border);
+    //   let $nextBorders = this._findNextBorders($border);
+    //   let lastBorderIndex = $prevBorders.length - 1;
+      
+    //   $prevBorders.forEach(item => {
+    //     let $item = $(item);
+    //     let $paragraphItem = $item.parent();  
+    //     $item.remove();
+    //     if (isEmptyElement($paragraphItem)) {
+    //       $paragraphItem.remove();
+    //     }
+    //   })
+
+    //   $nextBorders.forEach(item => {
+    //     let $item = $(item);
+    //     let $paragraphItem = $item.parent();
+    //     $item.remove();
+    //     if (isEmptyElement($paragraphItem)) {
+    //       $paragraphItem.remove();
+    //     }
+    //   })
+
+    //   let $paragraphBorderItem = $border.parent();
+
+    //   $border.remove();
+    //   if (isEmptyElement($paragraphBorderItem)) {
+    //     $paragraphBorderItem.remove();
+    //   }
+    //   $menu[0].blur();
+
+    //   this._checkRemovePage();
+
+    //   setTimeout(() => {
+    //     this._checkoutContentChangeByFun();
+    //   }, 100)
+    // })
+
+    // 删除结束
+  },
+ /**
+ * function 获取前一栏
+ */
+  _getPrevColumn: function ($column) {
+    let prev = $column[0].previousSibling;
+    let pageIndex = parseInt($column.attr('data-column-page')) - 1;
+    if (prev) {
+      if (prev.className && prev.className.indexOf('js-column') > -1) {
+        return $(prev);
+      } else {
+        if (pageIndex < 0) {
+          return false;
+        }
+
+        let prevPage = this.pages[pageIndex];
+        let lastColumnIndex = prevPage.$colums.length - 1;
+        return prevPage.$colums[lastColumnIndex] || false;
+      }
+    } else {
+      if (pageIndex < 0) {
+        return false;
+      }
+
+      let prevPage = this.pages[pageIndex];
+      let lastColumnIndex = prevPage.$colums.length - 1;
+      return prevPage.$colums[lastColumnIndex] || false;
+    }
+  },
+  // 获得该框以上的框
+  _findPrevBorders: function ($border) {
+    let $paragraph = getParentByClassname($border, 'js-paragraph-view');
+    let index = $paragraph.attr('data-index');
+    // 如果上一段在同一栏,则返回空
+    let prevParagraph = $paragraph[0].previousSibling;
+    if (prevParagraph && prevParagraph.className && prevParagraph.className.indexOf('js-paragraph-view') > -1) {
+      let firstContent = prevParagraph.firstChild;
+      if (firstContent && firstContent.className && firstContent.className.indexOf('js-answer-header') < 0) {
+        return [];
+      }
+    }
+
+
+    // 获取上一栏的最后一段
+    let $lastParagraph = this._getPrevColumnLastParagraph($paragraph);
+
+    if (!$lastParagraph) {
+      return [];
+    }
+
+    let prevIndex = $lastParagraph.attr('data-index');
+    let prevLastParagraph = $lastParagraph.attr('class');
+
+
+    if (index === prevIndex) {
+      let borders = [];
+      let lastBorder = $lastParagraph[0].lastChild;
+      borders.push(lastBorder);
+      if ($lastParagraph[0].childNodes.length === 1 && lastBorder.className && lastBorder.className.indexOf('js-lsiten-border') > -1 && prevLastParagraph.indexOf('js-split-paragraph') > -1) {
+        let prevBorders = this._findPrevBorders($(lastBorder));
+        borders = borders.concat(prevBorders);
+      }
+      return borders;
+    } else {
+      return [];
+    }
+
+  },
+  // 获取该框以上的问题
+  _findPrevQustions: function ($border, type) {
+    if ( type === 4) {
+      let $title = $border.find('.lsiten-title');
+      if ($title.length) {
+        return [];
+      }
+    }
+
+    let $paragraph = getParentByClassname($border, 'js-paragraph-view');
+    let index = $paragraph.attr('data-index');
+    // 如果上一段在同一栏,则返回空
+    let prevParagraph = $paragraph[0].previousSibling;
+    if (prevParagraph && prevParagraph.className && prevParagraph.className.indexOf('js-paragraph-view') > -1) {
+      let firstContent = prevParagraph.firstChild;
+      if (firstContent && firstContent.className && firstContent.className.indexOf('js-answer-header') < 0) {
+        return [];
+      }
+    }
+
+
+    // 获取上一栏的最后一段
+    let $lastParagraph = this._getPrevColumnLastParagraph($paragraph);
+
+    if (!$lastParagraph) {
+      return [];
+    }
+
+    let prevIndex = $lastParagraph.attr('data-index');
+    let prevLastParagraph = $lastParagraph.attr('class');
+
+    if (index === prevIndex) {
+      let lastBorder = $lastParagraph[0].lastChild;
+      let borderContent = lastBorder.firstChild;
+      if (borderContent) {
+        let lastQuestion = borderContent.lastChild;
+        let questionType = parseInt(lastQuestion.getAttribute('data-type'));
+        let questions = [];
+        if (type === questionType) {
+          questions.push(lastQuestion);
+  
+          if (borderContent.childNodes.length === 1 && prevLastParagraph.indexOf('js-split-paragraph') > -1) {
+            let prevQuestions = this._findPrevQustions($(lastBorder), type);
+            questions = questions.concat(prevQuestions);
+          }
+          return questions;
+        } else {
+          return [];
+        }
+      } else {
+        return [];
+      }
+
+    } else {
+      return [];
+    }
+    
+  },
+  // 获取上一栏的最后一段
+  _getPrevColumnLastParagraph: function ($paragraph) {
+      let $colum = getParentByClassname($paragraph, 'js-column');
+      if (!$colum) {
+        return null;
+      }
+  
+      let $prevColumn = this._getPrevColumn($colum);
+  
+      if (!$prevColumn) {
+        return null;
+      }
+  
+      let $paragraphs = $prevColumn.find('.js-paragraph-view');
+  
+      if (!$paragraphs.length) {
+        return null;
+      }
+  
+      let lastIndex = $paragraphs.length - 1;
+  
+      let lastParagraph = $paragraphs[lastIndex];
+  
+      let first = lastParagraph.firstChild;
+      if (first.className && first.className.indexOf('js-answer-header') > -1) {
+        return null;
+      }
+  
+      return $(lastParagraph);
+  
+    },
+  
+  _findNextBorders: function ($border) {
+      let $paragraph = getParentByClassname($border, 'js-paragraph-view');
+      let index = $paragraph.attr('data-index');
+      // 如果上一段在同一栏,则返回空
+      let nextParagraph = $paragraph[0].nextSibling;
+      if (nextParagraph && nextParagraph.className && nextParagraph.className.indexOf('js-paragraph-view') > -1) {
+        let firstContent = nextParagraph.firstChild;
+        if (firstContent && firstContent.className && firstContent.className.indexOf('js-answer-header') < 0) {
+          return [];
+        }
+      }
+  
+      // 获取下一栏的第一段
+      let $firstParagraph = this._getNextColumnfirstParagraph($paragraph);
+  
+      if (!$firstParagraph) {
+        return [];
+      }
+  
+      let nextIndex = $firstParagraph.attr('data-index');
+  
+      let nextFirstParagraph = $firstParagraph.attr('class');
+  
+      if (index === nextIndex) {
+        let borders = [];
+        let firstBorder = $firstParagraph[0].firstChild;
+        borders.push(firstBorder);
+        if ($firstParagraph[0].childNodes.length === 1 && firstBorder.className && firstBorder.className.indexOf('js-lsiten-border') > -1 && nextFirstParagraph.indexOf('js-split-paragraph') > -1) {
+          let nextBorders = this._findNextBorders($(firstBorder));
+          borders = borders.concat(nextBorders);
+        }
+        return borders;
+      } else {
+        return [];
+      }
+  },
+  // 获取该框以下的问题
+  _findNextQustions: function ($border, type) {
+      let $paragraph = getParentByClassname($border, 'js-paragraph-view');
+      let index = $paragraph.attr('data-index');
+      // 如果上一段在同一栏,则返回空
+      let nextParagraph = $paragraph[0].nextSibling;
+      if (nextParagraph && nextParagraph.className && nextParagraph.className.indexOf('js-paragraph-view') > -1) {
+        let firstContent = nextParagraph.firstChild;
+        if (firstContent && firstContent.className && firstContent.className.indexOf('js-answer-header') < 0) {
+          return [];
+        }
+      }
+  
+      // 获取下一栏的第一段
+      let $firstParagraph = this._getNextColumnfirstParagraph($paragraph);
+  
+      if (!$firstParagraph) {
+        return [];
+      }
+  
+      let nextIndex = $firstParagraph.attr('data-index');
+  
+      let nextFirstParagraph = $firstParagraph.attr('class');
+  
+      if (index === nextIndex) {
+        let firstBorder = $firstParagraph[0].firstChild;
+        let borderContent = firstBorder.firstChild;
+        if (borderContent) {
+          let firstQuestion = borderContent.firstChild;
+          let questionType = parseInt(firstQuestion.getAttribute('data-type'));
+          let questions = [];
+          if (type === questionType) {
+            questions.push(firstQuestion);
+    
+            if (borderContent.childNodes.length === 1 && nextFirstParagraph.indexOf('js-split-paragraph') > -1) {
+              let nextQuestions = this._findNextQustions($(firstBorder), type);
+              questions = questions.concat(nextQuestions);
+            }
+            return questions;
+          } else {
+            return [];
+          }
+        } else {
+          return [];
+        }
+  
+      } else {
+        return [];
+      }
+  },
+  
+  // 获取下一栏的第一段
+  _getNextColumnfirstParagraph: function ($paragraph) {
+      let $colum = getParentByClassname($paragraph, 'js-column');
+      if (!$colum) {
+        return null;
+      }
+  
+      let $nextColumn = this._getNextColumn($colum);
+  
+      if (!$nextColumn) {
+        return null;
+      } 
+  
+      let $paragraphs = $nextColumn.find('.js-paragraph-view');
+  
+      if (!$paragraphs.length) {
+        return null;
+      }
+  
+      let firstParagraph = this._cycleFindParagraph($paragraphs[0]);
+      if (!firstParagraph) {
+        return null;
+      }
+  
+      let firstContent = firstParagraph.firstChild;
+      if (firstContent && firstContent.className && firstContent.className.indexOf('js-answer-header') > -1) {
+        return null;
+      }
+  
+      return $(firstParagraph);
+  },
+  
+  
+  // 循环查找段落 
+  _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;
   },
    /** 
    * function 内容变化事件监听