再战“所见即所得”富文本编辑器(附 原创工具)

未尽的事业

2014 年底,我为了搞定 电邮签名档 做了次专门的研发,非常有收获!但它依然有个 ——

外置 CSS 样式 要人工一一填到 HTML 标签的 style 属性中,图片也要自己转换成 Base64 编码……

2016 年初,我又遇到需要手写 富文本电邮的一件事,手工转换一个大网页 —— 累个半死…… 同时,女友也在为“微信公众平台 图文消息编辑器 不能在文章正文加超链接”发愁,想用我当年开发的 HTML 代码注入工具 除了学会写 静态网页代码,还是要我手工转换为 单一网页格式(类似 Internet Explorer .mht)……

编程马拉松

基于不久前对 CSS 对象的深入研究,我用之前两个夜晚的饭后休息时间完成了一个 网页代码 行内化工具的开发、测试 ——

javascript: (function (BOM, DOM) {
  /* ---------- 生效样式 ---------- */

  function Tag_Computed_CSS(iDOM) {
    return JSON.parse(
      JSON.stringify(iDOM.ownerDocument.defaultView.getComputedStyle(iDOM))
    );
  }

  /* ---------- 原始样式 ---------- */

  var Tag_Style = {},
    iSandBox = DOM.createElement('iframe');

  iSandBox.style.display = 'none';
  DOM.body.appendChild(iSandBox);

  function Tag_Default_CSS(iTagName) {
    var _DOM_ = iSandBox.contentWindow.document;

    if (!Tag_Style[iTagName]) {
      var iDefault = _DOM_.createElement(iTagName);
      _DOM_.body.appendChild(iDefault);
      Tag_Style[iTagName] = Tag_Computed_CSS(iDefault);
      _DOM_.body.removeChild(iDefault);
    }
    return Tag_Style[iTagName];
  }

  /* ---------- 变更样式 ---------- */

  function Tag_Customed_CSS() {
    var iCustomed = {},
      iComputed = Tag_Computed_CSS(arguments[0]),
      iDefault = Tag_Default_CSS(arguments[0].tagName.toLowerCase());

    for (var iAttr in iComputed)
      if (
        isNaN(Number(iAttr)) &&
        !iAttr.match(/^(moz|webkit|ms)/) &&
        iComputed[iAttr] != iDefault[iAttr] &&
        !iAttr.match(/width|height/i)
      )
        iCustomed[iAttr] = iComputed[iAttr];

    return iCustomed;
  }

  /* ---------- 内联化核心 ---------- */

  BOM.CSS_Inline = function () {
    var iStyle = Tag_Customed_CSS(arguments[0]);

    for (var iAttr in iStyle) arguments[0].style[iAttr] = iStyle[iAttr];
  };

  BOM.Image_Inline = function (iDOM, iWaterMark) {
    var _Image_ = new Image(),
      iCanvas = DOM.createElement('canvas');

    _Image_.crossOrigin = '';
    var iContext = iCanvas.getContext('2d');

    _Image_.onload = function () {
      iCanvas.width = _Image_.width;
      iCanvas.height = _Image_.height;
      iContext.drawImage(_Image_, 0, 0);

      if (iWaterMark) {
        iContext.font = '20px sans-serif';
        iContext.fillStyle = 'white';
        iContext.fillText(iWaterMark, 10, _Image_.height - 15);
      }
      iDOM.src = iCanvas.toDataURL('image/png');
      _Image_ = null;
    };
    _Image_.src = iDOM.src;
  };

  BOM.Web_Inline = function () {
    var iTag = arguments[0].querySelectorAll('*');

    for (var i = 0; i < iTag.length; i++)
      switch (iTag[i].tagName.toLowerCase()) {
        case 'meta':
        case 'style':
        case 'script':
        case 'iframe':
          iTag[i].parentNode.removeChild(iTag[i]);
          break;
        case 'img':
          this.Image_Inline(iTag[i], arguments[1]);
          break;
        default:
          this.CSS_Inline(iTag[i]);
      }
    return arguments[0].innerHTML.trim();
  };

  /* ---------- 使用流程 ---------- */

  BOM.Web_Inline(DOM.body, BOM.prompt('图片水印文字:'));

  BOM.setTimeout(function () {
    DOM.body.textContent = DOM.body.innerHTML;
    BOM.alert('请全选、复制当前显示的所以代码~');
  }, 1000);
})(self, self.document);

上一篇
Intel XDK 跨平台 App 开发初体验 Intel XDK 跨平台 App 开发初体验
用 HTML/CSS/JavaScript 进行移动端 App 跨平台开发的开源旗手非 Adobe PhoneGap 莫属,它的开源核心 Apache Cordova 就像 Apple Safari、Google Chrome 的 Webk
2016-06-21
下一篇
【原创】Docker LAMP 入门 【原创】Docker LAMP 入门
LAMP 服务器套件(Linux + Apache + MySQL + PHP)早已成为 Web 应用开发者 最常用的部署环境,几乎是入门必修课,但它的搭建、维护也是对初学者很艰难的一课。虽然有 XAMPP 这样的跨平台一键安装包,但它们主
2015-11-17
目录