123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- /**
- * 目录大纲支持插件
- * @file
- * @since 1.3.0
- */
- UE.plugin.register("section", function() {
- /* 目录节点对象 */
- function Section(option) {
- this.tag = "";
- (this.level = -1), (this.dom = null);
- this.nextSection = null;
- this.previousSection = null;
- this.parentSection = null;
- this.startAddress = [];
- this.endAddress = [];
- this.children = [];
- }
- function getSection(option) {
- var section = new Section();
- return utils.extend(section, option);
- }
- function getNodeFromAddress(startAddress, root) {
- var current = root;
- for (var i = 0; i < startAddress.length; i++) {
- if (!current.childNodes) return null;
- current = current.childNodes[startAddress[i]];
- }
- return current;
- }
- var me = this;
- return {
- bindMultiEvents: {
- type: "aftersetcontent afterscencerestore",
- handler: function() {
- me.fireEvent("updateSections");
- }
- },
- bindEvents: {
- /* 初始化、拖拽、粘贴、执行setcontent之后 */
- ready: function() {
- me.fireEvent("updateSections");
- domUtils.on(me.body, "drop paste", function() {
- me.fireEvent("updateSections");
- });
- },
- /* 执行paragraph命令之后 */
- afterexeccommand: function(type, cmd) {
- if (cmd == "paragraph") {
- me.fireEvent("updateSections");
- }
- },
- /* 部分键盘操作,触发updateSections事件 */
- keyup: function(type, e) {
- var me = this,
- range = me.selection.getRange();
- if (range.collapsed != true) {
- me.fireEvent("updateSections");
- } else {
- var keyCode = e.keyCode || e.which;
- if (keyCode == 13 || keyCode == 8 || keyCode == 46) {
- me.fireEvent("updateSections");
- }
- }
- }
- },
- commands: {
- getsections: {
- execCommand: function(cmd, levels) {
- var levelFn = levels || ["h1", "h2", "h3", "h4", "h5", "h6"];
- for (var i = 0; i < levelFn.length; i++) {
- if (typeof levelFn[i] == "string") {
- levelFn[i] = (function(fn) {
- return function(node) {
- return node.tagName == fn.toUpperCase();
- };
- })(levelFn[i]);
- } else if (typeof levelFn[i] != "function") {
- levelFn[i] = function(node) {
- return null;
- };
- }
- }
- function getSectionLevel(node) {
- for (var i = 0; i < levelFn.length; i++) {
- if (levelFn[i](node)) return i;
- }
- return -1;
- }
- var me = this,
- Directory = getSection({ level: -1, title: "root" }),
- previous = Directory;
- function traversal(node, Directory) {
- var level,
- tmpSection = null,
- parent,
- child,
- children = node.childNodes;
- for (var i = 0, len = children.length; i < len; i++) {
- child = children[i];
- level = getSectionLevel(child);
- if (level >= 0) {
- var address = me.selection
- .getRange()
- .selectNode(child)
- .createAddress(true).startAddress,
- current = getSection({
- tag: child.tagName,
- title: child.innerText || child.textContent || "",
- level: level,
- dom: child,
- startAddress: utils.clone(address, []),
- endAddress: utils.clone(address, []),
- children: []
- });
- previous.nextSection = current;
- current.previousSection = previous;
- parent = previous;
- while (level <= parent.level) {
- parent = parent.parentSection;
- }
- current.parentSection = parent;
- parent.children.push(current);
- tmpSection = previous = current;
- } else {
- child.nodeType === 1 && traversal(child, Directory);
- tmpSection &&
- tmpSection.endAddress[tmpSection.endAddress.length - 1]++;
- }
- }
- }
- traversal(me.body, Directory);
- return Directory;
- },
- notNeedUndo: true
- },
- movesection: {
- execCommand: function(cmd, sourceSection, targetSection, isAfter) {
- var me = this,
- targetAddress,
- target;
- if (!sourceSection || !targetSection || targetSection.level == -1)
- return;
- targetAddress = isAfter
- ? targetSection.endAddress
- : targetSection.startAddress;
- target = getNodeFromAddress(targetAddress, me.body);
- /* 判断目标地址是否被源章节包含 */
- if (
- !targetAddress ||
- !target ||
- isContainsAddress(
- sourceSection.startAddress,
- sourceSection.endAddress,
- targetAddress
- )
- )
- return;
- var startNode = getNodeFromAddress(
- sourceSection.startAddress,
- me.body
- ),
- endNode = getNodeFromAddress(sourceSection.endAddress, me.body),
- current,
- nextNode;
- if (isAfter) {
- current = endNode;
- while (
- current &&
- !(
- domUtils.getPosition(startNode, current) &
- domUtils.POSITION_FOLLOWING
- )
- ) {
- nextNode = current.previousSibling;
- domUtils.insertAfter(target, current);
- if (current == startNode) break;
- current = nextNode;
- }
- } else {
- current = startNode;
- while (
- current &&
- !(
- domUtils.getPosition(current, endNode) &
- domUtils.POSITION_FOLLOWING
- )
- ) {
- nextNode = current.nextSibling;
- target.parentNode.insertBefore(current, target);
- if (current == endNode) break;
- current = nextNode;
- }
- }
- me.fireEvent("updateSections");
- /* 获取地址的包含关系 */
- function isContainsAddress(startAddress, endAddress, addressTarget) {
- var isAfterStartAddress = false,
- isBeforeEndAddress = false;
- for (var i = 0; i < startAddress.length; i++) {
- if (i >= addressTarget.length) break;
- if (addressTarget[i] > startAddress[i]) {
- isAfterStartAddress = true;
- break;
- } else if (addressTarget[i] < startAddress[i]) {
- break;
- }
- }
- for (var i = 0; i < endAddress.length; i++) {
- if (i >= addressTarget.length) break;
- if (addressTarget[i] < startAddress[i]) {
- isBeforeEndAddress = true;
- break;
- } else if (addressTarget[i] > startAddress[i]) {
- break;
- }
- }
- return isAfterStartAddress && isBeforeEndAddress;
- }
- }
- },
- deletesection: {
- execCommand: function(cmd, section, keepChildren) {
- var me = this;
- if (!section) return;
- function getNodeFromAddress(startAddress) {
- var current = me.body;
- for (var i = 0; i < startAddress.length; i++) {
- if (!current.childNodes) return null;
- current = current.childNodes[startAddress[i]];
- }
- return current;
- }
- var startNode = getNodeFromAddress(section.startAddress),
- endNode = getNodeFromAddress(section.endAddress),
- current = startNode,
- nextNode;
- if (!keepChildren) {
- while (
- current &&
- domUtils.inDoc(endNode, me.document) &&
- !(
- domUtils.getPosition(current, endNode) &
- domUtils.POSITION_FOLLOWING
- )
- ) {
- nextNode = current.nextSibling;
- domUtils.remove(current);
- current = nextNode;
- }
- } else {
- domUtils.remove(current);
- }
- me.fireEvent("updateSections");
- }
- },
- selectsection: {
- execCommand: function(cmd, section) {
- if (!section && !section.dom) return false;
- var me = this,
- range = me.selection.getRange(),
- address = {
- startAddress: utils.clone(section.startAddress, []),
- endAddress: utils.clone(section.endAddress, [])
- };
- address.endAddress[address.endAddress.length - 1]++;
- range.moveToAddress(address).select().scrollToView();
- return true;
- },
- notNeedUndo: true
- },
- scrolltosection: {
- execCommand: function(cmd, section) {
- if (!section && !section.dom) return false;
- var me = this,
- range = me.selection.getRange(),
- address = {
- startAddress: section.startAddress,
- endAddress: section.endAddress
- };
- address.endAddress[address.endAddress.length - 1]++;
- range.moveToAddress(address).scrollToView();
- return true;
- },
- notNeedUndo: true
- }
- }
- };
- });
|