为编辑器创建网络组件

时间:2019-06-06 14:17:21

标签: javascript html web-component ace-editor

我想制作一个Web组件标签,其中包含具有一些附加功能的编辑器。我现在正在使用ACE-JSON编辑器。

主要代码是这个,我确实还有其他一些js文件。

<!DOCTYPE HTML>
<html>

<head>
  <title>JSONEditor</title>
  <meta charset="utf-8">
  <link href="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.32.5/jsoneditor.css" rel="stylesheet" type="text/css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.32.5/jsoneditor.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
  <script src="app.js"></script>
  <!-- <script src="worker.js"></script> -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

  <style>
    html,
    body {
      font: 11pt sans-serif;
    }

    #jsoneditor {
      width: 700px;
      height: 600px;
    }

    #paste,
    #link,
    #file {
      margin-top: 25px;
      align-content: center;

    }
  </style>
</head>

<body>
  <div class="container-fluid">
    <h1 align="center">Load and save JSON documents</h1>
    <br><br><br>
    <div class="row">
      <div class="col">
        <div id="jsoneditor"></div>
      </div>
      <div class="col col-centered">
        <div class="row">
          <div class="col">
            <select id="test" name="form_select" onchange="showDiv(this)">
              <option value="paste">paste json</option>
              <option value="file">Upload file</option>
              <option value="link">use link</option>
            </select>
          </div>
          <div class="col">
            <p>
              Save a JSON document: <input type="button" id="saveDocument" value="Save" />
            </p>
          </div>
        </div>
        <div class="row">
          <div class="col">
            <div id="file" style="display: none;" class="col-sm col-centered">
              Load a JSON document: <input type="file" id="loadDocument" value="Load" />
              <button class="button" onclick="readFile()">LOAD JSON</button>
            </div>
            <div id="paste" style="display: none;" class="col-sm col-centered">
              <h3>Paste JSON data </h3>
              <textarea id="myText" rows="4" cols="50"></textarea>
              <button class="button" onclick="loadText()">LOAD JSON</button>
            </div>
            <div id="link" style="display: none;" class="col-sm col-centered">
              <h3>URL</h3>
              <input type="text" id="url">
              <button class="button" onclick="urlOnclick()">LOAD JSON</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

<script>
  var options = {
    mode: 'tree',
    modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
    onError: function (err) {
      alert(err.toString());
    },
    onModeChange: function (newMode, oldMode) {
      console.log('Mode switched from', oldMode, 'to', newMode);
    }
  };
  // create the editor
  var editor = new JSONEditor(document.getElementById('jsoneditor'), options);

  // Save a JSON document
  document.getElementById('saveDocument').onclick = function () {
    // Save Dialog
    fname = window.prompt("Save as...");

    // Check json extension in file name
    if (fname.indexOf(".") == -1) {
      fname = fname + ".json";
    } else {
      if (fname.split('.').pop().toLowerCase() == "json") {
        // Nothing to do
      } else {
        fname = fname.split('.')[0] + ".json";
      }
    }
    var blob = new Blob([editor.getText()], { type: 'application/json;charset=utf-8' });
    saveAs(blob, fname);
  };
</script>

</html>

如何将其包装在Web组件中? 我使用JS进行了尝试,但是大多数教程都给出了一个简单标签的小例子。该网站的大部分内容都指向聚合物,但我没有找到关于我想做什么的适当参考。 请您为我提供指导或提供一些参考。

1 个答案:

答案 0 :(得分:0)

第三方库通常不设计用于Web组件。

您将遇到的问题是jQuery和jQuery插件的使用。创建Web组件时,您正在#document-fragment的{​​{1}}组件中创建#shadowRoot。这意味着我们用于选择元素(shadowDOM)的标准DOM语句将无法在document.getElementById(...)中选择元素。这是因为shadowDOM与根文档是隔离的。因此,您只能找到简单标签的示例。

JSONEditor,例如uses document.createElement() extensively

我已将您的HTML / JS转换为Web组件 ,由于上述原因,该组件无法正常运行 。这至少将向您展示如何进行更复杂的示例。

如下面的示例所示,很容易将外部脚本和样式表加载到组件中。可以使用模块shadowDOM的语法,而不是创建脚本标签,但是这些库不支持该语法。

以下是关键的运动部件:

  1. 代表自定义元素逻辑的ES6类
  2. 您的HTML已放置在import标记内,该标记用于保存自定义元素的DOM元素
  3. 此语句使自定义元素可用:
    • <template>
  4. customElements.define('my-editor', MyEditor);放入HTML文件

有关详细信息,请参阅源代码注释。

<my-editor></my-editor>
class MyEditor extends HTMLElement {
  constructor () {
    super();
    this.requiredScripts = [
      'https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js',
      'https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js',
      'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js',
      'https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.32.5/jsoneditor.js',
      'https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js',
    ];
    // Grab a reference to the custom element
    let template = document.getElementById('my-custom-editor');
    // Get the #document-fragment
    let templateContent = template.content;
    // Place the template from the Web Component in to the active DOM
    this.attachShadow({ mode: 'open' }).appendChild(templateContent.cloneNode(true));
  }
  // lifecycle hook that fires when custom element is placed into DOM
  connectedCallback () {
    // load required external resources
    this.loadScripts(0);
  }
  
  loadScripts (idx) {
    const tag = document.createElement('script');
    tag.src = this.requiredScripts[idx];
    tag.onload = () => {
      if (idx < this.requiredScripts.length - 1) {
        // when a script has finished, go get the next one
        this.loadScripts(++idx);
      } else {
        // Once all the script files are loaded, initialize the working parts of the component
        this.initEditor();
      }
    }
    tag.onload.bind(this);
    document.head.appendChild(tag);
  }
  
  initEditor () {
    // Need a reference to the #document-fragment
    // Every instance of "document" in this method has been replaced with "component"
    const component = document.getElementById('my-custom-editor').content;
    const options = {
      mode: 'tree',
      modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
      onError: function (err) {
        alert(err.toString());
      },
      onModeChange: function (newMode, oldMode) {
        console.log('Mode switched from', oldMode, 'to', newMode);
      }
    };
    // create the editor IN THE compoent (rathar than the DOM)
    var editor = new JSONEditor(component.getElementById('jsoneditor'), options);
    component.getElementById('saveDocument').onclick = function () {
      fname = window.prompt("Save as...");
      if (fname.indexOf(".") == -1) {
        fname = fname + ".json";
      } else {
        if (fname.split('.').pop().toLowerCase() == "json") {
        } else {
          fname = fname.split('.')[0] + ".json";
        }
      }
      var blob = new Blob([editor.getText()], {
        type: 'application/json;charset=utf-8'
      });
      saveAs(blob, fname);
    };
    
  }
}

customElements.define('my-editor', MyEditor);
html,
body {
    font: 11pt sans-serif;
}

相关问题