123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- /**
- * 目录大纲支持插件
- * @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
- }
- }
- }
- });
|