`

DOMLazyTree

 
阅读更多

DOMLazyTree模块用于向文档中插入、替换节点,以更新子节点或html或text。

setInnerHTML模块设置节点的innerHTML。

setTextContent模块为文本节点添加nodeValue,其他节点添加textContent或经转义后的innerHTML。

createMicrosoftUnsafeLocalFunction模块用于使ie浏览器禁用func函数的html安全筛选(通常是拼接节点时),非ie浏览器直接返回回调。

 

DOMLazyTree.js

'use strict';

// 节点命名空间的集合
var DOMNamespaces = require('./DOMNamespaces');

// 为节点添加innerHTML
var setInnerHTML = require('./setInnerHTML');

// ie浏览器禁用func函数的html安全筛选(通常是拼接节点时),非ie浏览器直接返回回调
var createMicrosoftUnsafeLocalFunction = require('./createMicrosoftUnsafeLocalFunction');

// 文本节点添加nodeValue,其他节点添加textContent或经html转义后的innerHTML
var setTextContent = require('./setTextContent');

var ELEMENT_NODE_TYPE = 1;
var DOCUMENT_FRAGMENT_NODE_TYPE = 11;

// IE8-11或Edge下,向文档插入含子节点的节点要快于插入含子节点的节点
var enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || 
  typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && 
  /\bEdge\/\d/.test(navigator.userAgent);

// 将tree.children或tree.html或tree.text插入tree.node中
function insertTreeChildren(tree) {
  if (!enableLazy) {
    return;
  }
  var node = tree.node;
  var children = tree.children;
  if (children.length) {
    for (var i = 0; i < children.length; i++) {
      insertTreeBefore(node, children[i], null);
    }
  } else if (tree.html != null) {
    setInnerHTML(node, tree.html);
  } else if (tree.text != null) {
    setTextContent(node, tree.text);
  }
}

// 将tree.node插入文档,并塞入newTree.children或newTree.html或newTree.text
var insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) {
  // DocumentFragments、<object> plugins (like Flash Player)需要先插入子节点,然后再插入文档
  if (tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE 
    || tree.node.nodeType === ELEMENT_NODE_TYPE && tree.node.nodeName.toLowerCase() === 'object' 
    && (tree.node.namespaceURI == null || tree.node.namespaceURI === DOMNamespaces.html)) {
    insertTreeChildren(tree);
    parentNode.insertBefore(tree.node, referenceNode);
  } else {
    parentNode.insertBefore(tree.node, referenceNode);
    insertTreeChildren(tree);
  }
});

// 将节点从oldNode替换成newTree.node,并塞入newTree.children或newTree.html或newTree.text
function replaceChildWithTree(oldNode, newTree) {
  oldNode.parentNode.replaceChild(newTree.node, oldNode);
  insertTreeChildren(newTree);
}

// IE8-11或Edge,将子节点存储在tree.children中,DOMLazyTree.insertTreeBefore方法调用时再行插入子节点
// 其他浏览器,直接将子节点插入tree.node下
function queueChild(parentTree, childTree) {
  if (enableLazy) {
    parentTree.children.push(childTree);
  } else {
    parentTree.node.appendChild(childTree.node);
  }
}

// IE8-11或Edge,将html存储在tree.html中,DOMLazyTree.insertTreeBefore方法调用时再行插入html
// 其他浏览器,直接将html插入tree.node下
function queueHTML(tree, html) {
  if (enableLazy) {
    tree.html = html;
  } else {
    setInnerHTML(tree.node, html);
  }
}

// IE8-11或Edge,将text存储在tree.text中,DOMLazyTree.insertTreeBefore方法调用时再行插入text
// 其他浏览器,直接将text插入tree.node下
function queueText(tree, text) {
  if (enableLazy) {
    tree.text = text;
  } else {
    setTextContent(tree.node, text);
  }
}

// 返回tree.node.nodeName
function toString() {
  return this.node.nodeName;
}

function DOMLazyTree(node) {
  return {
    node: node,
    children: [],
    html: null,
    text: null,
    toString: toString
  };
}

// insertTreeBefore(parentNode,tree,referenceNode)将tree.node插入文档,并塞入newTree.children或newTree.html或newTree.text
DOMLazyTree.insertTreeBefore = insertTreeBefore;

// replaceChildWithTree(oldNode,newTree)将节点从oldNode替换成newTree.node,并塞入newTree.children或newTree.html或newTree.text
DOMLazyTree.replaceChildWithTree = replaceChildWithTree;

// queueChild(parentTree,childTree)插入子节点,IE8-11或Edge先存储于tree.children中,insertTreeBefore方法调用时再插入文档
DOMLazyTree.queueChild = queueChild;

// queueHTML(tree,html)插入子节点,IE8-11或Edge先存储于tree.html中,insertTreeBefore方法调用时再插入文档
DOMLazyTree.queueHTML = queueHTML;

// queueText(tree,text)插入子节点,IE8-11或Edge先存储于tree.text中,insertTreeBefore方法调用时再插入文档
DOMLazyTree.queueText = queueText;

module.exports = DOMLazyTree;

 

setInnerHTML.js

'use strict';

var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');

// 节点命名空间的集合
var DOMNamespaces = require('./DOMNamespaces');

var WHITESPACE_TEST = /^[ \r\n\t\f]/;// 空格符匹配
var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/;

// ie浏览器禁用func函数的html安全筛选(通常是拼接节点时),非ie浏览器直接返回回调
var createMicrosoftUnsafeLocalFunction = require('./createMicrosoftUnsafeLocalFunction');

var reusableSVGContainer;

var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
  // 为svg节点或普通dom节点赋予html内容
  if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {
    reusableSVGContainer = reusableSVGContainer || document.createElement('div');
    reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
    var svgNode = reusableSVGContainer.firstChild;
    while (svgNode.firstChild) {
      node.appendChild(svgNode.firstChild);
    }
  } else {
    node.innerHTML = html;
  }
});

if (ExecutionEnvironment.canUseDOM) {
  var testElement = document.createElement('div');
  testElement.innerHTML = ' ';
  if (testElement.innerHTML === '') {
    setInnerHTML = function (node, html) {
      // IE8更新节点时空白字符将表现出怪异,重新添加节点能处理空白字符的怪异表现
      if (node.parentNode) {
        node.parentNode.replaceChild(node, node);
      }

      // 包含空格或以"<"开头、包含NONVISIBLE_TEST中字符
      if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) {
        // 节点的innerHTML前插入字符String.fromCharCode(0xFEFF),作为node的首个节点firstChild
        // 再通过node.removeChild或textNode.deleteData方法移除该文本子节点
        // String.fromCharCode(0xFEFF)是出于对UglifyJS清除U+FEFF的考虑
        node.innerHTML = String.fromCharCode(0xFEFF) + html;

        var textNode = node.firstChild;
        if (textNode.data.length === 1) {
          node.removeChild(textNode);
        } else {
          textNode.deleteData(0, 1);
        }
      } else {
        node.innerHTML = html;
      }
    };
  }
  testElement = null;
}

// 设置节点的innerHTML
module.exports = setInnerHTML;

 

setTextContent.js

'use strict';

var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');

// 布尔型和数值型转化为字符串后输出;字符串经html转码,逐个字符处理["'&<>]
var escapeTextContentForBrowser = require('./escapeTextContentForBrowser');

// 为节点添加innerHTML
var setInnerHTML = require('./setInnerHTML');

// 文本节点添加nodeValue,其他节点添加textContent
var setTextContent = function (node, text) {
  if (text) {
    var firstChild = node.firstChild;

    if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) {
      firstChild.nodeValue = text;
      return;
    }
  }
  node.textContent = text;
};

if (ExecutionEnvironment.canUseDOM) {
  // 文本节点添加nodeValue,其他节点添加转义后的innerHTML
  if (!('textContent' in document.documentElement)) {
    setTextContent = function (node, text) {
      if (node.nodeType === 3) {
        node.nodeValue = text;
        return;
      }
      setInnerHTML(node, escapeTextContentForBrowser(text));
    };
  }
}

module.exports = setTextContent;

 

createMicrosoftUnsafeLocalFunction.js

'use strict';

// ie浏览器禁用func函数的html安全筛选(通常是拼接节点时),非ie浏览器直接返回回调
var createMicrosoftUnsafeLocalFunction = function (func) {
  // MSApp.execUnsafeLocalFunction(func),ie下为指定函数funct禁用html安全筛选,通常是拼接节点时
  if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
    return function (arg0, arg1, arg2, arg3) {
      MSApp.execUnsafeLocalFunction(function () {
        return func(arg0, arg1, arg2, arg3);
      });
    };
  } else {
    return func;
  }
};

module.exports = createMicrosoftUnsafeLocalFunction;

 

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics